I did something similar to half-close or fully close my shades when it was (a) hot, (b) sun was strong and (c) the sun was on my windows).
To do this, I needed to know:
- sun azimuth (it it +/- 60° to the window’s direction)
- sun elevation (as it needs to clear the house opposite)
- direction my window is viewing (N,S,E,W) as my house pretty much faces due North
- external light level - Night, Dark, Grey, Bright (for 30 secs to avoid clouds and headlights etc).
- temperature.
- UV (to help determine the sun’s intensity)
This is the template sensor that decides if my south-facing windows are in the sun (I have similar for east and west).
template:
- binary_sensor:
# South is 150°±60° = 90°➜210°
- name: "shades south has sun"
state: >
{{
states('sensor.home_sun_azimuth')|float(150) >= 90
and states('sensor.home_sun_azimuth')|float(150) <= 210
and states('sensor.home_sun_elevation')|float(45) >5
}}
icon: "{{ iif(states('binary_sensor.shades_south_has_sun') == 'on', 'mdi:weather-sunny', 'mdi:umbrella-outline') }}"
I also using a custom_template
which determines the shades position:
{% macro shade_level(shade, dir, contact) %}
{% set privacy = states('input_number.' ~ shade ~ '_shade_privacy_position') %}
{% set sun = states('binary_sensor.shades_' ~ dir ~ '_has_sun') %}
{% set open = states('binary_sensor.' ~ shade ~ '_' ~ contact ~ '_contact') %}
{% set light = states('sensor.light_level_30s') %}
{% set sunup = states('binary_sensor.sun_up') %}
{% set sundown = states('binary_sensor.dusk_to_dawn') %}
{% set house = states('input_select.house_mode') %}
{% set uv = states('sensor.weather_uv_index')|float(0) %}
{% set uv_min = states('input_number.shade_uv_trigger_level')|float(5) %}
{% set cond = states('sensor.local_weather_condition') %}
{% set t_in = states('sensor.hottest_temp')|float(15) %}
{% set t_half = states('input_number.shade_50_trigger_temp')|float(22) %}
{% set t_close = states('input_number.shade_closed_trigger_temp')|float(24) %}
{# night / asleep #}
{% if (light == 'Night' and sunup == 'off') or house == 'Asleep' or sundown == 'on' %}
{% if open == 'off' %} 0
{% else %} 50
{% endif %}
{# Dark #}
{% elif light== 'Dark' and sunup == 'off' and house == 'Awake' %}
{% if open == 'off' %} {{privacy}}
{% else %} 50
{% endif %}
{# hot day #}
{% elif sun == 'on' and uv >= uv_min and cond in ['partlycloudy','sunny'] %}
{# full #}
{% if t_in >= t_close %}
{% if open == 'off' %} 0
{% else %} 50
{% endif %}
{# half #}
{% elif t_in >= t_half %} 50
{% endif %}
{% else %} 100
{% endif %}
{% endmacro %}
The custom_template uses binary_sensor.sun_up
and binary_sensor.dusk_to_dawn
.
- name: "dusk to dawn"
unique_id: sun_dwn
state: >
{{
now() > state_attr('sensor.home_sun_dusk','today')
or
now() < state_attr('sensor.home_sun_dawn','today')
}}
- name: "sun_up"
unique_id: sun_up
state: "{{ states('sensor.home_sun_elevation')|round(1) >6.0 }}"
Finally, here is a template sensor to set my shade:
- name: "Bedroom 1 shade target position"
unit_of_measurement: "%"
state: >
{% from 'shades.jinja' import shade_level %}
{{ shade_level('bedroom_1', 'south', 'window') }}
I use the fantastic sun2 integration to get some of these sensors.
I appreciate this is not exactly what you are looking for but it might help steer you. Note that I did it this way as I have a bunch of shades in windows looking in different directions and each one’s position isn’t only effected by a ‘hot day’ but also whether my house is awaken and whether the associated window is open etc etc etc.
[edited to simplify by removing 2 unnecessary templates and add the shade target height template]
2nd edit: For this to work, I need the following for each shade:
cover. x_shade
binary_sensor. x_contact # contact sensor
input_boolean. x_shade_automation_enabled
input_number. x_shade_night_position
input_number. x_shade_privacy_position
sensor. x_shade_reported_position
sensor. x_shade_target_position
The custom_templates
variables passed are
x for 'cover.x_shade'
direction 'north', 'south', 'east' or 'west'
contact sensor w/o 'binary_sensor.' or '_contact' ending