Circadian light with Philips Hue, independent from world clocks ;-)

hi @mastermarkush

would you recognize this error:

2018-07-20 09:50:24 ERROR (MainThread) [homeassistant.helpers.entity] Update for sensor.circadian_light fails
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 196, in async_update_ha_state
    yield from self.async_device_update()
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 317, in async_device_update
    yield from self.async_update()
  File "/usr/local/lib/python3.6/asyncio/coroutines.py", line 212, in coro
    res = func(*args, **kw)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/sensor/template.py", line 183, in async_update
    self._state = self._template.async_render()
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/template.py", line 132, in async_render
    return self._compiled.render(kwargs).strip()
  File "/usr/local/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 76, in render
    return original_render(self, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 1008, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 3, in top-level template code
TypeError: can't multiply sequence by non-int of type 'float' 

which change would you suggest to mitigate the error in these 2 sensors:

  - platform: template
    sensors:
      length_of_day_factor:
        friendly_name: 'Length of day' # factor for circadian light calculation'
        value_template: >
            {% set daylength = ((as_timestamp(states.sun.sun.attributes.next_setting) - 
                                 as_timestamp(states.sun.sun.attributes.next_rising)) / 
                                 3600) + 24 %}
              {{ ((daylength*-0.0063616)+0.11131)|round(5) }}

      circadian_light:
        friendly_name: 'Circadian light'
        unit_of_measurement: 'mired'
        value_template: >
          {% if is_state('sun.sun' , 'above_horizon') %}
            {{ ((states.sensor.length_of_day_factor.state | round (5)) * 
               ((states.sun.sun.attributes.azimuth)-180)**2 + 175) | int }}
          {% elif (as_timestamp(states.sun.sun.attributes.next_dusk)) - 
                  (as_timestamp(states.sun.sun.attributes.next_setting)) < 0 or 
                  (as_timestamp(states.sun.sun.attributes.next_rising)) - 
                  (as_timestamp(states.sun.sun.attributes.next_dawn)) < 0 %}
            350
          {% else %}
            390
          {% endif %}

not sure if the error is caused by the HA startup sequence not having set the value correctly yet, or the template is not correct?

Thx for having another check,
Marius

Hi @Mariusthvdb,
I have also seen this error in my config from time to time. It refers to the sensor.circadian_light which cannot be calculated. From what I see, the template itself is ok, I concluded that this might be due to a) either a point of time where the values couldn’t be calculated e.g. during startup or b) during dusk periods when - even if only for a short moment - the circadian light sensor calculates a value (sun = above horizon), the daylength sensor however provides no value.

This might be because of the way I calculate the length of the day: based on the NEXT day. Since NEXT days are either getting longer or shorter compared to today, this might create some tiny hick-ups.

getting back to this, Id propose this change in the value_template:

      {% if is_state('sun.sun' , 'above_horizon') %}
        {{ ((states('sensor.length_of_day_factor') | default(0) | round (5)) * 
           ((state_attr('sun.sun','azimuth'))-180)**2 + 175) | round }}

It creates a startup value, which prevents the error mentioned in my post above and changes the |int to round.

error gone.

I dont understand yet why the round(5) is needed both in the sensor.length_of_day and in the template using the state of that sensor. Seems to be superfluous?
I took the round(5) out of the circadian_light sensor, but that does not work…?

---- edit----

well, that was a one timer i think, the error came back. Ive now changed it to:

    {{ ((states('sensor.length_of_day_factor') | round (5)) * 
       ((state_attr('sun.sun','azimuth') )-180)**2 + 175) | round }}

so at least they’re both floats. No error this time, lets hope it stays that way

Thanks,
Marius

Hi Marius, I just came across your project and want to implement it in our dining and living room. Could you send me the Calc sheet so I can tweek the settings a bit?

Best,
Reinhard

I would also love a copy of your Excel work. I’m working on a native Node-RED pallet that duplicates this functionality and picking up from your work would be so incredibly helpful!

1 Like

@mastermarkush Would love to get a look into the file as well!

@mastermarkush, I would love to see your Excel file, as well. Could you maybe create a gist with the file and share the link?

You can download the mired calculation file in my github repository: https://github.com/mastermarkush/homeassistant

1 Like

Hi, thank you for sharing this!
I integrated your sensors in my config and will check the graphs in the following days to see if the constants need some adjusting.
Anyway, trying to avoid the errors on startup, I also modified the colortemp template as per recommendations and so far no errors popped up:

    colortemp:
      friendly_name: 'Circadian light - color temperature'
      unit_of_measurement: 'mired'
      value_template: >
          {% if is_state('sun.sun' , 'above_horizon') %}
            {{ ((states('sensor.length_of_day_factor') | round (5)) * ((state_attr('sun.sun','azimuth') )-180)**2 + 175) | int }}
          {% elif ((as_timestamp(state_attr('sun.sun','next_dusk'))) - (as_timestamp(state_attr('sun.sun','next_setting'))) < 0) or ((as_timestamp(state_attr('sun.sun','next_rising'))) - (as_timestamp(state_attr('sun.sun','next_dawn'))) < 0) %}
            390
          {% else %}
            500
          {% endif %}

Best,
R

Is it possible to have multiple zones of lights set this or do they called by the single instance? I have the switch loaded in my office, but was thinking it would be nice for this to work in my kitchen or bedroom as well.

Hi @atmasphere! I think I didn’t get your question right. What I understood is that you want to have multiple (independent) lights apply the mechanics of adaptive “circadian” light. If so, then simply apply the colortemp variable to the color_temp in the data_template for the specific light or group of lights that you turn on… Maybe you can reformulate your question?

think you understand but to be clear, I’d like to have a switch for multiple rooms.

Office lights are currently utlizing this (though it broke for some reason). I was thinking I’d like to turn it on for my kitchen and bedroom as well but want the ability to turn the toggle on and off by room.

broken switch in place but this is my office view -

Screenshot_10

Dear @mastermarkush,

could I use this to automate my window roller shutters with this component? If yes, would you give a short hint, how?

What I’d like have is a little fixed time delay, so not to close the shutters instantly as dawn kicks in, but like 30 mins later or so…

many thanks in advance

Hi John,
for this use case I’d suggest you to have a look at my other project which relates more to automations around day periods.

Cheers,
Markus

Hi @mastermarkush
Would it be possible for you to send me your mired calculation file? I looked at your github site, but looks like it’s no longer there.
Really cool work.
Thank you.
Mark

hm, thx Markus, looks interesting, I’ll dig into it :slight_smile:

Hi Mark, I re-uploaded the mired calculation file.
-Markus

Fantastic, thx Markus for all your efforts!!
Best Mark

that’s the least I can do, given the tremendous support that I get from this community…

1 Like

Are these magic numbers geographic location depending perhaps?
I’ve tried it now (for a Hungarian location), and it goes to -339 mired soon after sunset for a few minutes:
screenshot-8123-2021.02.09-20_15_03

It is because with this formula, length_of_day_factor becomes -0.1056 after being 0.0471 for most of the day.
Or perhaps sun.above_horizon isn’t in sync with sun.next_setting?