Do you think solar noon is a reliable trigger for predicting when the sun doesn't shine through my window anymore during sunny months?

For a month now, around solar noon has been the time when the sun stopped shining through my working room window and I could raise the curtains again.
I don’t know if it’s gonna be the same in September. What do you think?

It’d be nice if telling whether the sun shines through my window worked with only software sensors instead of illuminance sensors that cost money.

This is something you need to find out for yourself. You need to decide, what is comfortable for you, and what isn’t. :slight_smile:

But, you’re not the first one with such problems, so others already have found some solutions. :slight_smile:

Here is an integration from @basbrus, called adaptive cover, which does all the calculations for you. You just enter where your table is in the room, and the integration calculates how far the covers should be lowered. :slight_smile:

If you don’t want to go that way, there are other things you could try, like using the azimuth to calculate your comfort zone. You can use the sun2 component from @pnbruckner, which is an enhanced sun component:

Or you can do it by getting your personal comfort zone in the room with ThermalComfort. This integration gives you some very specific values, which you could use to determine if your temp and such things are still in your comfort zone.

Now it’s your turn. Which way do you want to go, or do you even want to combine these? :wink: :joy:

1 Like

Do the solutions that do the calculations for me work without automated window blinds? I’d fire notifications instead of window blind–commands, but I don’t want to be spammed with them. I just need one when the sun doesn’t shine at my window anymore.

Depends… :laughing: The integration (adaptive cover) won’t, but you could use the blueprint, where the integration is based on. It started as a blueprint and was later made into an integration.

With this, you should be able to “not control covers”, but rather send out a notification. Take the blueprint as a template, and build your own automation from it. Then it’s up to you, what you do, if the “covers” should lower.

Just to be clear, don’t use the blueprint as blueprint, but rather copy what you need from it and set this in your own automation. Eg. this is the code from the blueprint, where “the magic” happens.

cover_height: >
    {%- set deg2rad = pi/180 -%}
    {# normalize in range [0,1] #}
    {%- macro norm(x, min, max) %}
      {{ (x - min) / (max - min) }}
    {%- endmacro %}
    {# convert blind height h to percentage [0,100] #}
    {%- macro h2perc(x) %}
      {{ 100 * float(norm(x, h_min, h_max)) }}
    {%- endmacro %}
    {# clip value between [min, max] #}
    {%- macro clipv(x, x_min, x_max) %}
      {{ max(min(x, x_max), x_min) }}
    {%- endmacro %}
    {# constants #}
    {%- set win_azi = azimuth -%}
    {%- set left_azi = azimuth_left | default(90) -%}
    {%- set right_azi = azimuth_right | default(90) -%}
    {%- set elev_high = deg2rad * (max_elevation | default(90)) -%} {# Maximum: 90 #}
    {%- set elev_low = deg2rad * (min_elevation| default(0)) -%} {# Minimum: 0 #}
    {%- set d = distance | default(0.5) -%}
    {%- set h_max = max_height | default(2.10) -%}
    {%- set h_min = min_height | default(0) -%}
    {%- set deg = degrees | default(90) -%}
    {%- set def = default_height | default(60) -%}
    {%- set min_pos = min_position | default(0) -%}
    {%- set def_temp = default_template | default('') -%}
    {% if def_temp | int(-1) >= 0 %}
      {% set def = def_temp %}
    {%endif%}

    {# FOV #}
    {%- if left_azi != right_azi-%}
      {%- set azi_left = deg2rad * -left_azi -%} {# Minimum: -90 #}
      {%- set azi_right = deg2rad * right_azi -%} {# Maximum: 90 #}
    {%-else-%}
      {%- set azi_left = deg2rad * -deg -%} {# Minimum: -90 #}
      {%- set azi_right = deg2rad * deg -%} {# Maximum: 90 #}
    {%-endif-%}
    {%- set fov = deg2rad * deg -%}
    {# get sun elevation / azimuth from sun.sun #}
    {%- set sun_azi = state_attr('sun.sun', 'azimuth') -%}
    {%- set sun_ele = state_attr('sun.sun', 'elevation') -%}
    {# default height, when automatic control is off. #}
    {%- set def_h = def / 100 * h_max -%}
    {%- set alpha = deg2rad * sun_ele -%}
    {% set gamma = deg2rad * ((win_azi - sun_azi + 180) % 360 - 180) %}    
    {%- set h = (d / cos(gamma)) * tan(alpha) -%}
    {# gamma is outside of FOV #}
    {%- if gamma < azi_left or gamma > azi_right or alpha < elev_low or alpha > elev_high -%}
      {{ clipv(h2perc(def_h) | round(0) | int , 0, 100) }}
    {# gamma is inside of FOV #}
    {%- else -%}  
      {{ clipv(h2perc(h) | round(0) | int , min_pos, 100) }}
    {%- endif -%}
  change_threshold: !input change_threshold
  time_out: !input time_out
  condition_mode: !input condition_mode
  dict_var: >
    {%- set ns = namespace(list_1=[],name_1=[],list_2=[],name_2=[]) %}
    {%- set  entity = cover_entity['entity_id'] -%}
    {%- if entity is iterable and (entity is not string and entity is not mapping) -%}
      {%- set cover = entity -%}
    {%- else -%}
      {%- set cover = [entity] -%}
    {%- endif -%}
    {%- for c in cover %}
      {%- set position = state_attr(c,'current_position') | int -%}
      {%- set con_1 = ((position - cover_height | float) | abs >= change_threshold)
      or (cover_height in [default_height, default_template] and position not in [default_height, default_template])%}
      {%- set ns.list_1 = ns.list_1 + [con_1]  -%}
      {%- set con_2 = now() - timedelta(minutes=time_out) >= states[c].last_updated %}
      {%- set ns.list_2 = ns.list_2 + [con_2] %}
      {%- if con_1 == true -%}
        {%- set ns.name_1 = ns.name_1 + [c] -%}
      {% endif %}
      {%if con_2 == true%}
        {%- set ns.name_2 = ns.name_2 + [c] -%}
      {% endif %}
    {%endfor%}
    {%- set dict = {
      'condition_1':ns.list_1,
      'condition_2':ns.list_2,
      'names_1':ns.name_1,
      'names_2':ns.name_2
      } %}
    {{dict}}
  condition_1: >
    {{true is in dict_var['condition_1']}}
  condition_2: >
    {{true is in dict_var['condition_2']}}
  entities_1: >
    {{dict_var['names_1']}}
  entities_2: >
    {{dict_var['names_2']}}

And this is the complete blueprint:

I don’t understand what happens even in the first code snippet. Just copypasting it into a template-trigger for an automation with an action that notifies me to raise the curtains doesn’t work.

I just use azimuth from sun.sun - when it’s between 57 and 0, the sun is in my window. So I set up a binary template sensor “sun in window” that is on between these values. Then when it goes from off to on I close the blind, and open it again when it goes on to off.

If you have an east or west facing window then solar noon should (I think) work every day of the year since it’s at that moment the sun is at it’s vertical point in the sky no matter which time of year. But if you have a south or north facing window the elevation will make a difference as to how far the sun will penetrate thru the window even at it’s solar noon - lower to the horizon it will shine further into the room.

I think…

Actually the integration also provides (binary)sensors when you don’t setup a cover entity. You still get the binary sensor that shows if the sun shines through the configured window :wink:.

2 Likes

I use this for adjusting my blinds throughout the day in my office and it works superbly. Pretty sure this is what the code posted above is referencing.

https://community.home-assistant.io/t/incident-angle-of-sunlight/444646

EDIT:

Just saw that there is an updated version linked in the thread but I’m still using the one I linked with no issues. Will check out the updated version to see if I should implement.

If you mean the Vertical End Sun sensor, what would a template trigger for it look like?

The sensor @basbrus refers to, is binary_sensor.{type}_sun_infront_{name}, I’d guess in your case it should be something like binary_sensor.vertical_sun_infront_manuelle_jalousie. That binary_sensor is ‘on’, when the sun is in front of the window.

Do you need a more specific trigger?

1 Like