Circadian Lighting [Custom Component]

@claytonjn Can there be a check added for the light’s color temperature range? I’m seeing errors with negative values for colortemp.

example: Circadian color temperature range is 2000-4000K. This works fine for lights which go as low as 2000 and high as 4000. But if a light only goes to 2100, the switch still attempts to set 2000 and gets an error and doesnt change the temperature.

ERROR (MainThread) [homeassistant.core] Error executing service <S erviceCall light.turn_on (c:85e6c83e18674ab1a85bb6233cf85d6d): entity_id=[‘light.bedro om_wall_lamps’], color_temp=588, brightness=161, transition=0.0>
Traceback (most recent call last):
File “/srv/homeassistant/lib/python3.6/site-packages/homeassistant/components/light/ xiaomi_miio.py”, line 286, in _try_command
partial(func, *args, **kwargs))
File “/usr/local/lib/python3.6/concurrent/futures/thread.py”, line 56, in run
result = self.fn(*self.args, **self.kwargs)
File “/srv/homeassistant/lib/python3.6/site-packages/miio/philips_bulb.py”, line 139 , in set_brightness_and_color_temperature
raise PhilipsBulbException(“Invalid color temperature: %s” % cct)
miio.philips_bulb.PhilipsBulbException: Invalid color temperature: -158

I have another use case for different sensors (color) settings, as discussed above, there, and there

In the same room, I have same light bulbs in different appliances and different “light projections”
As I like my wall lights going from min to max colortemp because wall color is greyish/whiteish, I like to have a cutoff on the lunch table, to avoid an uncomfortable effect (already had complaint from wife or guests “we feel like in an hospital”).

I fix it with an high cut filter in my automation

automation
- alias: 'Lampes Table couleur'
  initial_state: 'on'
  trigger:
  - entity_id: light.yeelight_ct2_7c49ebb7d46a
platform: state
to: 'on'
  - entity_id: sensor.circadian_values
platform: state
  condition:
  - condition: state
entity_id: light.yeelight_ct2_7c49ebb7d46a
state: 'on'
  action:
  - service: light.turn_on
data_template: 
    entity_id: light.yeelight_ct2_7c49ebb7d46a # Table salon
    # transition: >
    #     {%- if as_timestamp(now()) - as_timestamp(states.automation.lampes_table_couleur.attributes.last_triggered) > 10 -%}
    #         {{ states.sensor.circadian_values.attributes.transition | int }}
    #     {%- else -%}
    #         2
    #     {%- endif -%}
    kelvin: >
        {%- if states.sensor.circadian_values.attributes.colortemp <= 3921 -%}
            {{ states.sensor.circadian_values.attributes.colortemp | int }}
        {%- else -%}
            3921
        {%- endif -%}

(I have yet to make the transisition part working)

I could do this because it seems that all lights report max_mireds and min_mireds (at least mine do - Hue and Lightify), however it would require querying the light attributes for every selected light, and doing some logic to figure out the min and max of all lights selected, every single time the code runs (every interval). That also assumes that the min_mireds and max_mireds values are correct. I think it would be much better for the user to just figure it out once during the initial setup and have the code me more efficient…

I appreciate your input, but again, this goes against the core intention of this component. Honestly, if you’re allowing any lights to bypass the circadian values you’re throwing off your biological rhythm so there’s really no point in having this component at all - if they think it’s like a hospital that’s probably because hospitals are designed to make patients comfortable. There are other components/methods you can use to allow varying color temperature throughout the day, Circadian Lighting specifically is focusing on keeping everything in sync to maximize the biological benefits. At this time I have no plans on programming in any way to allow color temperature to be out of sync between groups of lights, the in-place overrides are intended for one-off temporary overrides. The only real argument I’ve considered for taking color temperature at the switch level is when different model lights appear different when set to the same CT but even that is something I want to avoid compensating for because it should be fixed at the device level.

Hi Clayton,

I am in this case:

The only real argument I’ve considered for taking color temperature at the switch level is when different model lights appear different(not different lights but different reflective material.

Overall, all my lights are in sync in all my appartment. I listen and respect your arguments. Lights are different in hospital/restaurant/lounge bar for a purpose I think. (I’m not going that far). Because off the direct light exposition and white reflector on this specific light, I guess it appears agressive compared to the wall paint that may “absorb” some part of the light spectra.

BTW I will think about keeping or not my “low pass filter”, or set the whole lights the same.

Overall, CL improved our life, many thanks Clayton !

Thanks for the component, I’m currently testing it to replace flux in my setup :slight_smile:

Do you have plans to get this mainlined at some point?

Btw, with embedded platforms it is now possible to contain the code inside a single directory (which would allow it to be easily pulled from a git repository), here’s the structure under ~/.homeassistant:

custom_components/circadian_lighting/
custom_components/circadian_lighting/__init__.py
custom_components/circadian_lighting/switch.py
custom_components/circadian_lighting/sensor.py

1 Like

hi all,
i may have a stupid question, can anyone tell me when the lights should be brightest?
it’s pitch dark outside here (around 10 pm) and the lights are at around 30% (which is just a little bit above my min_brightness
Is my assumption correct that it will go darker the later it is in the day?

Sure, I’d love to, at some point.

Thanks, I do plan on making this change as soon as I have time.

1 Like

Yes, they start at max_brightness at sunset, dim down to min_brightness (half way between sunset and sunrise) then brighten back to max_brightness at sunrise.

@claytonjn

Can you make this plugin compatible with this plugin?

Or it is already compatible?

See his response to my comment above, from the page you linked

@claytonjn, others

I had an idea: during evening, I want my kitchen lights to be on low brightness when nobody is in the kitchen.And turn to a higher brightness when somebody enters the kitchen.
I made something that works, kind off. My config for this, looks like this:

circadian_lighting:
  interval: '20'
  transition: '20'

switch:
  - platform: circadian_lighting
    name: Tradfri_GU10
    lights_ct:
      - light.tradfri_bulb_10
      - light.tradfri_bulb_11
      - light.tradfri_bulb_12
      - light.tradfri_bulb_8
      - light.tradfri_bulb_9
    min_brightness: 31
    max_brightness: 70
    disable_entity: 'binary_sensor.motion_sensor_xyz'
    disable_state: 'off'
  - platform: circadian_lighting
    name: Tradfri_GU10_dimmed
    lights_ct:
      - light.tradfri_bulb_10
      - light.tradfri_bulb_11
      - light.tradfri_bulb_12
      - light.tradfri_bulb_8
      - light.tradfri_bulb_9
    max_brightness: 40
    disable_entity: 'binary_sensor.motion_sensor_xyz'
    disable_state: 'on'

in the HA log I see 10 errors after a restart (all the same as shown below), they must be linked to the above configuration.

Error doing job: Future exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/switch/circadian_lighting.py", line 332, in light_state_changed
    self.adjust_lights([entity_id], 1)
  File "/config/custom_components/switch/circadian_lighting.py", line 266, in adjust_lights
    if self.should_adjust():
  File "/config/custom_components/switch/circadian_lighting.py", line 259, in should_adjust
    elif self._attributes['disable_entity'] is not None and self.hass.states.get(self._attributes['disable_entity']).state == self._attributes['disable_state']:
AttributeError: 'NoneType' object has no attribute 'state'

So I must be doing something that’s not correct.

Can maybe someone provide some help? Is there a better way to implement this?

Basically what’s happening is that the Circadian Lighting switches are being initialized before your motion_sensor_xyz, so when CL tries to check the state there’s nothing there.

I think there’s a way with async to have CL wait until the disable_entity exists before trying to query the state…I’ve been wanting to implement async but I have no experience with it and haven’t had the time to learn.

In the mean time I should probably have it check if the entity exists yet before checking its state, but for now you should be able to just ignore the error.

OK, thank you for the explanation.I will ignore the errors :slight_smile:

Can I ask you about advice regarding my implementation?
Right now, the switch from low brightness to high brightness is not instantaneous. It takes at least 20 seconds.
I can decrease the numbers even more, but I wonder, is there another way to implement this?
I tried something with the “circadian_lighting.values_update” service, but that did no do anything.

Not sure if this is quite what you want but I have my lights set up for 3 modes:ON, OFF, AUTO (motion controlled) where in AUTO I have Circadian Lighting turned ON, but in ON mode I have CL OFF. This way if I want the kitchen light ON for cooking etc, I’m not trying to do so in low, orange light. This is all done with automations, CL switches and Xiaomi wireless buttons. I have the same for the ensuite light so my girlfriend can do her make-up in decent light for example, but later at night the light would generally be in AUTO mode so it turns ON with motion and is set low and reddish.

As I say, I’m not sure that it is quite what you are chasing but maybe an idea to think about.

1 Like

How do you achieve this?

I use packages. Here is my ensuite light one:

ensuite_light.yaml

# All code relating to the ensuite light

automation:
  - alias: Ensuite Remote Button
    initial_state: 'on'
    trigger:
      - platform: event
        event_type: xiaomi_aqara.click
        event_data:
          entity_id: binary_sensor.switch_158d00016bf679
          click_type: single
      - platform: event
        event_type: xiaomi_aqara.click
        event_data:
          entity_id: binary_sensor.switch_158d00016bf679
          click_type: double
      - platform: event
        event_type: xiaomi_aqara.click
        event_data:
          entity_id: binary_sensor.switch_158d00016bf679
          click_type: long_click_press

    action:
      - service_template: >
          {% if trigger.event.data.click_type == 'single' %}
            script.ensuite_button_single_click
          {% elif trigger.event.data.click_type == 'double' %}
            script.ensuite_button_double_click
          {% elif trigger.event.data.click_type == 'long_click_press' %}
            script.ensuite_button_long_press
          {% endif %}
          


  - alias: Ensuite light auto ON motion
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: binary_sensor.motion_sensor_158d0001ad43db
        to: 'on'
    condition:
      condition: or
      conditions:
      - condition: sun
        after: sunset
        after_offset: '-00:10:00'
      - condition: sun
        before: sunrise
        before_offset: '-01:00:00'
    action:
      service: light.turn_on
      entity_id: light.ensuite_light


  - alias: Ensuite light OFF after 2mins
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: binary_sensor.motion_sensor_158d0001ad43db
        to: 'off'
        for:
          minutes: 1
    action:
      - service: homeassistant.turn_off
        entity_id: light.ensuite_light

script:
  ensuite_button_single_click:
    alias: Ensuite button single click
    sequence:
    - service: switch.turn_off
      data:
        entity_id: switch.circadian_lighting_ensuite_circadian_lighting
    - service: light.turn_on
      data:
        entity_id: light.ensuite_light
        brightness: 255
        rgb_color: [255,255,255]
    - service: automation.turn_off
      data:
        entity_id: 
          - automation.ensuite_light_auto_on_motion
          - automation.ensuite_light_off_after_2mins
  
  ensuite_button_double_click:
    alias: Ensuite button double click
    sequence:
    - service: light.turn_off
      data: 
        entity_id: light.ensuite_light
    - service: automation.turn_off
      data:
        entity_id: 
          - automation.ensuite_light_auto_on_motion
          - automation.ensuite_light_off_after_2mins
  
  ensuite_button_long_press:
    alias: Ensuite button long press
    sequence:
    - service: switch.turn_on
      data:
        entity_id: switch.circadian_lighting_ensuite_circadian_lighting
    - service: automation.turn_on
      data:
        entity_id: 
          - automation.ensuite_light_auto_on_motion
          - automation.ensuite_light_off_after_2mins
2 Likes

I just upgraded to version 0.86.4 and now get errors that circadian_lighting cannot load anymore. From the log file:;

2019-01-31 08:03:41 ERROR (MainThread) [homeassistant.loader] Error loading custom_components.switch.circadian_lighting. Make sure all dependencies are installed
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/loader.py", line 117, in _load_file
    module = importlib.import_module(path)
  File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 673, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/home/homeassistant/.homeassistant/custom_components/switch/circadian_lighting.py", line 16, in <module>
    from homeassistant.helpers.restore_state import async_get_last_state
ImportError: cannot import name 'async_get_last_state'
2019-01-31 08:03:41 ERROR (MainThread) [homeassistant.loader] Error loading custom_components.circadian_lighting.switch. Make sure all dependencies are installed
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/loader.py", line 117, in _load_file
    module = importlib.import_module(path)
  File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
ImportError: No module named 'custom_components.circadian_lighting.switch'; 'custom_components.circadian_lighting' is not a package
2019-01-31 08:03:41 ERROR (MainThread) [homeassistant.loader] Unable to find platform circadian_lighting

any ideas what is going wrong?

Not sure, it’s working for me.

This line is interesting:
ImportError: No module named 'custom_components.circadian_lighting.switch'; 'custom_components.circadian_lighting' is not a package

Do you have the latest version from GitHub? If so, I would try reorganizing the files as described here: Circadian Lighting [Custom Component]

I am not sure which version I have. The date stamp is from Dec 6.What is the latest version?

Setting the file up as tepprr proposes does not change the issue. It did work for 0.85 and before so maybe I should report an issues at home assistant.