Template entity to guess the outside colour temperature

template:
  - sensor:
    - name: sun_colour_temp
      state: "{{ [ [ (1000000/(4791.67 - 3290.66/(1 + 0.222 * [ [ 0, state_attr('sun.sun', 'elevation') ] | max, 90 ] | min**0.81)))|int, 250 ] | max, 454 ] | min }}"
      unique_id: 2022031530eeb1d67b44fef54447eb835a17b4ca
      unit_of_measurement: 'Mireds'

This will create a new sensor.sun_colour_temp who’s value is the colour temperature outside in Mireds - the unit used by many colour temperature changing bulbs. I have constrained the values to between 250 and 454 as that is what my bulbs are limited to

I then use an automation to update the colour temperature of all my bulbs when sensor.sun_colour_temp changes.

Explanation

  1. First it gets the ‘elevation’ attribute from sun.sun (in all default HA installations)
  2. It constrains sun.sun’s elevation to positive values between 0 (sunset/sunrise) and 90 (midday)
  3. It then applies a custom calculation to the elevation to calculate the colour temperature, I derived this formula from a graph in an academic paper, more importantly, I have been testing it and have found it to work well.
  4. Rounds to the nearest integer
  5. It then constrains the output to the range 250 - 454 which is the range of my IKEA Tradfri bulbs support

For colour temperature in Kelvin, you can try this (untested), adjust 2200 and 4000 to the supported range of your bulbs:
{{ [ [ (1000000/(4791.67 - 3290.66/(1 + 0.222 * [ [ 0, state_attr('sun.sun', 'elevation') ] | max, 90 ] | min**0.81)))|int, 2200] | max, 4000] | min }}
Edit: Removed unnecessary/legacy sensor and added Explanation

6 Likes

Cool!

But why are you creating the sun_elevation entity and don’t use it in the second sensor (not that it’s needed).
It seems to me as the first sensor is not needed.

Agreed, I will edit. -its because I had it configured differently before

What an awesome idea. Thanks for sharing!

Amazing timing, thanks for sharing, would it be possible to use this template for brightness level 0-100 instead?,

Not really, it would be overkill

Ok, I have a light that only supports brightness level and would like to control the brightness based on the sun elevation.

Wouldn’t that be simply


… int),0]|max),255] …

instead of


… int),250]|max),454] …

?

Except the formula is for a curve that is based on colour temperature not brightness. You could give it a go and see if it gives the desired results - I doubt you would though, it will almost never spit out a number near 0.

Sure enough, it doesn’t.

Link? (10 char min)

Dynamic Lighting System for Workplaces at Northern Latitudes Tarmo Koppel, Tallinn University of Technology

Then I reverse engineered an equation to fit the graph.

1 Like

Any idea how I mite be able to accomplish the same effect for brightness?

{{state_attr('sun.sun', 'elevation') + 10}} would give you a number that varies between 10 at sunrise/sunset and 100. If you use that to set brightness percentage…

Or {{state_attr('sun.sun', 'elevation') /90*100}} would vary between 0-100.

But beware the seasons and your latitude would effect the brightness. The sun only reaches maximum elevation in the summer. Unless you live on the equator…

Otherwise to get 100% brightness at midday every day and 0 at sunrise you need a different formula.

This post has info on getting the percentage of the day remaining Sun elevation based on percentage of day which is tangentially related to what you want to achieve

nice idea! IMO you’re overusing () which makes it more confusing. Math in code follows order of operations, many of those () are implied in the syntax

{{ [ [ (1000000/(4791.67 - 3290.66/(1 + 0.222 * [ [ 0, state_attr('sun.sun', 'elevation') ] | max, 90 ] | min**0.81)))|int, 250 ] | max, 454 ] | min }}
1 Like

Maybe {{state_attr('sun.sun', 'elevation') /1*2}}, since the max elevation these days is around 49°?

So, the following seems to work, what do you think?

service: light.turn_on
target:
  entity_id: light.white_led
data_template:
  brightness_pct: >-
    {{ (state_attr('sun.sun', 'elevation')| multiply(2) / 1 ) | round(0) }}

the /1 is doing nothing

{{ state_attr('sun.sun', 'elevation')| multiply(2) | round(0) }}

:+1: Yep, realized just after posting, ended up with the following, which seems to be working well so far.

alias: Large Tank Light by Elevation
description: Increase / Decrease Brightness by Elevation
trigger:
  - platform: state
    entity_id: sun.sun
    attribute: elevation
condition:
  - condition: time
    after: '07:00:00'
    before: '19:00:00'
  - condition: numeric_state
    entity_id: sun.sun
    above: '0'
    attribute: elevation
action:
  - service: light.turn_on
    data_template:
      brightness_pct: '{{ (state_attr(''sun.sun'', ''elevation'')| multiply(2)) | round(0) }}'
    target:
      entity_id: light.white_led
mode: single

You’d probably want to normalize the values based on the min/max elevation possible for your region. So that the highest point is 100%.

FYI, this entire thread can be solved by using the custom integration: Circadian lighting, or adaptive lighting. Both have the same functionality.