Where to employ the fresh devtools.template code

Hi there.

I have been working on a code to control roller shutters. Its now a code that works in devtools.template and produces the right output.

But where in HA do I put that code now. Or rather what is the best way forward now.

Ideally I would like to later go to automation and just add a new shutter based on a “template”, enter his variables and entity, check the global variables if they still fit and activate it.

This code contains lots of variables for one window in my house. and it contains the code that calculates from this variables the shutter position during the 24h of a day.

What it does:

  • If sun is height enough and inside the fitting azimuth, shading is active and the position of the shutter follows the sun to keep the amount of sun inside the house constant. (acceptable sun streak)
  • If sun is outside of azimuth limits, shutter is fully open
  • if sun is outside of elevation limits, shutter is fully open
  • during dawn and dusk the roller shutter is in slotted mode
  • in between dusk and dawn the shutter is closed

Not jet implemented is

  • check for cloud level
  • compare outdoor forecast temp at 2pm to indoor temp
  • activate shading if indoor temp limit is exceeded or if AC runs
  • minimum open for cat door or to prevent lock out on terrace door
  • shading with awning instead of roller shutter if present and its fallbacks
  • global and individual control module for permanent off, timed off and auto
  • switch from current elevation as shading true / false gate to todays maximum elevation (shading only during summer and autumn.

Of course the code needs still to be tidied up, I would appretierte some help in this area. But it may be better to do this when the codes finished.

{## Imitate available variables: ##}
{% set a = 180 %} {# direction the window is facing: default 180 = south #}
{% set b = 45 %} {# deviation from window direction shading is required: default 45 #}
{% set c = 0 %} {#deviation from vertical if e.g. roof window (a wall window is 0° deviation) #}
{% set d = 1000 %} {#height of window in mm #}
{% set e = 400 %} {#width of wall including inside window sill in mm #}
{% set f = 100 %} {#acceptable width of sun streaks (AWS) in mm #}
{% set g = 50 %} {#depth of the shutter from outside wall #}
{% set h = 98 %} {#start shading in % of roller shutter #}
{% set i = 5 %} {#fully shaded in % of roller shutter #}
{% set j = 68 %} {# formula needs to be build. from which elevation shading is no longer required because the wall itself provides shading #}
{% set k = 10 %} {# from which elevaiotn onward shading is required #}
{% set r = pi / 180  %} {#angle2radiant conversion factor#}
{% set azimuth = states('sensor.test_sun_azimuth') | float(0) %} {# free #}
{% set elevation = states('sensor.test_sun_elevation') | float(0) %} {# free #}
Dev.Info: Azimuth is: {{azimuth}}      Elevation is: {{elevation}}
{% if (a-b) < azimuth < (a+b) and elevation < j %} >{#must also check for clouds and temp before setting s = ture#}
  {% set shading = "true" %} 
{% else %}
  {% set shading = "false" %}
{% endif %}
Dev.Info: Shading required: {{ shading }}

Result:
{% if shading == "true" and elevation > k %}
  {% set cover_position = (((d+e)*tan(elevation*r)/d*10) | float(0)) | round(0) %} 
  ACTIVE shading at {{ cover_position }}% roller shutter position due to azimuth and elevation
{% elif shading != "true" and elevation > k-%}
  {% set cover_position = '100' | float(0) %} 
  OPEN and NOT shading due to azimuth limitation
{% elif elevation < -6 %}
  {% set cover_position = '0' | float(0) %} 
  CLOSED for night due to elevation < -6°. Elevation: {{elevation}} 
{% elif -6 < elevation < 0 %}
  {% set cover_position = '10' | float(0) %} 
  SLOTTED for dawn and dusk due to elevation -6° <-> 0°. Elevation: {{elevation}} 
{% else %}
  {% set cover_position = '100' | float(0) %} 
  OPEN and NOT shading due to low elevation
{% endif %}

To have this code output a sensible result in devtools.template, one would need my test.sun implementation. Which can be found here: click

Thanks
Manne

I assume you want this to become a template sensor?
Template - Home Assistant (home-assistant.io)

paste it as the example in configuration.yaml

If you’re adjusting a cover or covers, you’d make this into a script that adjusts a number of cover positions with a cover.set_position service call, and this template would only output the position without the words. But the script will change based on how you want this to run. If this is running every few minutes, how are you populating the variables? There’s no such thing as ‘global variables’ in home assistant. So you need to have a way to provide variables via helpers or inputs to the script.

@Hellis81 i dont think template is the right way to go with this.

@petro what i kind of imagined was a set of kind of global set values as say manually set sensor values or so for the stuff the covers need.

since i calculate the shutter position during shading in reference to

  • wall thickness
  • window height
  • direction the window is facing
  • limitations of azimuth + and - from the direction of the window for this window
  • and some more

every single window will need its own automation since it got individual properties and shutter positions especially during shading operations.

therefore I thought one might go to the automations section in the GUI, create a new one and instead of starting with an empty template, select the roller-shutter-thing, that is filled with all the default values for a south facing window and comments on what to put where in the yaml editor, and then one only needs to enter the entitys delivering the required data like azimuth, elevation, cloud-level, forcast today 2pm and the smart device controlling the roller-shutter motor in yamel gui editor. If screwed up, just dump the thing and create new from template.

On the very first roller shutter one would also need to create those sticking sensors that contain the data for the roller-shutter-global part, so its all over the house the same, e.g. dawn and dusk handling or such stuff.

the global thing just like i created my test sun

  - trigger:
      - platform: time_pattern
        # This /1 will update every day      ### don't know if there is something like "on start"
        day: /1
    sensor:
      # set global start/end of night
      - name: "global_roller_shutter"
        unit_of_measurement: "°"
        state_class: measurement
        state: >
          {% set night = -6 | float %}

along those lines

The downside of what you’re saying is that you’ll have to cycle through covers because each one will have a separate postiion. This will give the appearance that they all move in order. Either way, I’d still go with a script that has your configuration for each cover. The downside is that you’ll have n scripts, 1 for each cover. The upside is that you’re config will be in 1 place for the cover.

The script for the single window.

  my_window:
    mode: single
    variables:
      cover: cover.my_window
      thickness: 1
      window_height: 5
      ...
    sequence:
    - service: script.turn_on
      target:
        entity_id: script.calculate_position
      data:
        cover: "{{ cover }}"
        thickness: "{{ thickness }}"
        window_height: "{{ window_height }}"
        ....

The script for calculating and apply calculation to ANY cover

calculate_position:
  mode: parallel
  sequence:
  - service: cover.set_position
    target:
      entity_id: "{{ cover }}"
    data:
      position: >
        ... tempalte that uses variables passed in data that calculates position...

Then you can use script.my_window anywhere and it will run the calculation and set the window.

1 Like

that sounds like a plan… i’ll try that one, and see if it is what I wanted. thanks @petro

ill be back

Your other option is to use customize.yaml and attach attributes that hold your custom information to each cover.

cover.my_cover:
  thickness: 1
  window_height: 1
  ...

Then make a single script where you pass the cover to it and it extracts all the attributes and uses them.

i think i actually like that one better, because adding a new window would just mean to copy the window section from one before and change the values of the attributes for the next one, right?

what would that change in regard to your before suggestion?

sorry for bothering you with all this beginner stuff

Yes

You wouldn’t need the individual scripts, you’d only have 1 script. But you’d have to extract the attributes from the cover for the calculation.

im new to this, do you have a suggestion for a how to or a documentation with some examples?

So i made some more corrections and gave all variables speaking names, its still the version developed in devtools.template. code is below.

If someone has a recommendation how to further improve the code, Im open for suggestions.

I tried to follow petros advice, but I got stuck in the integration process.

So I made the customize.yaml, and put the first windows values in.

But I dont know how to best proceed from there. Do I create a python script in the config folder or do i go to scripts and put it in there. and how do i get the values of my window in there?

I am thankfull for any hints or help.
Manne

{## Imitate available variables: ##}
{% set window_direction = 180 %} {# direction the window is facing: default 180 = south #}
{% set azimuth_limit_low = 45 %} {# lover deviation from window direction from which shading is required: default 45 #}
{% set azimuth_limit_high = 45 %} {# uper deviation from window direction up to wich shading is required: default 45 #}
{% set window_tilt = 0 %} {#deviation from vertical if e.g. roof window (a wall window is 0° deviation) #}
{% set widonw_height = 1000 %} {#height of window in mm #}
{% set window_wall_thickness = 400 %} {#width of wall including inside window sill in mm #}
{% set window_sun_strake = 100 %} {#acceptable width of sun streaks (AWS) in mm #}
{% set window_depth_roller_shutter = 50 %} {#depth of the shutter from outside wall #}
{% set roller_shutter_start_shading = 98 %} {#start shading in % of roller shutter #}
{% set roller_shutter_full_shading = 5 %} {#fully shaded in % of roller shutter #}
{% set roller_shutter_catdoor = 5 %} {#shutter max close setting for cat door or to prevent lock out from terrace door #}
{% set roller_shutter_max = 68 %} {# formula needs to be build. from which elevation shading is no longer required because the wall itself provides shading #}
{% set window_min_elevaiton_shading_active = 10 %} {# from which elevaiotn onward shading is required #}
{% set window_angle2radiant = pi / 180  %} {#angle2radiant conversion factor#}
{% set azimuth = states('sensor.test_sun_azimuth') | float(0) %} {# free #}
{% set elevation = states('sensor.test_sun_elevation') | float(0) %} {# free #}
Dev.Info: Azimuth is: {{azimuth}}      Elevation is: {{elevation}}
{% if (window_direction-azimuth_limit_low) < azimuth < (window_direction+azimuth_limit_high) and elevation < roller_shutter_max %} >{#must also check for clouds and temp before setting s = ture#}
  {% set shading = "true" %} 
{% else %}
  {% set shading = "false" %}
{% endif %}
Dev.Info: Shading required: {{ shading }}

Result:
{% if shading == "true" and elevation > window_min_elevaiton_shading_active %}
  {% set shading_rate = ((widonw_height+window_wall_thickness+window_wall_thickness)*(tan((elevation - window_tilt) * window_angle2radiant) / widonw_height * 10) | float(0)) | round(0) %} {# shading_rate muss noch in % roller_shuter umgerechnet werden#}
  ACTIVE shading at {{ shading_rate }}% roller shutter position due to azimuth and elevation
{% elif shading != "true" and elevation > window_min_elevaiton_shading_active %}
  {% set shading_rate = '100' | float(0) %} 
  OPEN and NOT shading due to azimuth limitation
{% elif elevation < -6 %}
  {% set shading_rate = '0' | float(0) %} 
  CLOSED for night due to elevation < -6°. Elevation: {{elevation}} 
{% elif -6 < elevation < 0 %}
  {% set shading_rate = '10' | float(0) %} 
  SLOTTED for dawn and dusk due to elevation -6° <-> 0°. Elevation: {{elevation}} 
{% else %}
  {% set shading_rate = '100' | float(0) %} 
  OPEN and NOT shading due to low elevation
{% endif %}

How’d you get stuck, the methods I provided are really your only options. Did you try anything or did you just update your code? To me, it looks like you’re still playing in the template editor.

actually I have fixed some issues in my code still in templet, stuff i missed before, like forgot to bring the roof window angle into the formula, then I renamed all variables to speaking names and made sure everything works still as intended. also found some error in one formula where i fixed the wrong stuff in brackets together and therefore got slightly wrong results. just slightly. just in this post i found some typos in my code. :slight_smile:

but I also fooled around with the customize.yaml, put in my sensors, defined the first global stuff, and did lots of reading in the docs. But I sill gained no traction in how to set up the script, but to more detail, I have no clue at all how I would get those values into the script.

this is my customize.yaml

# values for roller shutter script
  cover.global:
    cloud_level: 50
    prefer_awning: "false"
    indoor_temp: sensor.indoor_temperature
    local_rain: sensor.rain_rate
    local_wind: sensor.wind_wind
    local_gust: sensor.wind_gust
    local_azimuth: test.sun_azimuth
    local_elevation: test.sun_elevation

  cover.EG_kueche:
    window_direction: 180           # direction the window is facing: default 180 = south
    azimuth_limit_low: 45           # lover deviation from window direction from which shading is required: default 45 (positive value, also its negative of the window!)
    azimuth_limit_high: 45          # upper deviation from window direction up to wich shading is required: default 45
    window_tilt: 0                  # deviation from vertical if e.g. roof window (a wall window is 0° deviation)
    window_height: 1000             # height of window in mm
    window_wall_thickness: 400      # width of wall including inside window sill in mm
    window_sun_strake:  100         # acceptable width of sun streaks (AWS) in mm
    window_depth_roller_shutter: 50   # depth of the shutter from outside wall
    roller_shutter_start_shading: 98  # start shading in % of roller shutter
    roller_shutter_full_shading: 5    # fully shaded in % of roller shutter
    roller_shutter_catdoor: 5         # shutter max close setting for cat door or to prevent lock out from terrace door
    roller_shutter_max: 68            # formula needs to be build. from which elevation shading is no longer required because the wall itself provides shading
    window_min_elevation_shading_active: 10 # from which elevation onward shading is required
    window_angle2radiant: pi / 180    # angle2radiant conversion factor

This:

    indoor_temp: sensor.indoor_temperature

looks like you’re trying to create an attribute called indoor_temp that gets its value from another entity.

To do that correctly, you would need to use a template but customize.yaml doesn’t support the use of templates. Without support for templating, all you can do is assign a constant (i.e. this is fine: window_direction: 180).

The same rule applies to this:

window_angle2radiant: pi / 180

To perform that calculation it would need to be in a template (but templates aren’t supported here).

1 Like

Maybe there’s a disconnect but the whole point of templates is to use them inside a scripts in fields that accept templates. This is done through script variables or inside the data field itself. Have you created a script before with templates?

Extracting attributes works the same way as extracting a state. You need to use the method that extracts the attribute from the entity. I suggest you look at the templating docs and see what methods you have access to.

thanks you two, petro, i think that gave the notch, well see, if not ill be back here… and asking more stupid stuff.

123, your right, thats what I try to accomplish, so I could use a “constant” in my code and other folks using this, can just enter their value supplying devices (every body gets his stuff from some other hardware or online sources, so they dont need to mess with the stuff where all the formulas are) into one place.
i understand, I have to move the “constant” stuff, if they do mapping or calculations, to templates. right?

I think you’re miss understanding ‘global variables’ based on some previous knowledge of some other system. This is not that system. Wipe your mind.

If you need a sensors value at runtime of the script, simply use the states method to grab the state at the time you need it. There’s no reason to store it ‘globally’ because it’s already stored… as the current state of a sensor.

That makes this whole section pointless

and makes this variable pointless as well.

Because those will be pulled, used, or calculated at script execution time.

1 Like

thanks for this very detailed clarification, therefore i did actually understand 123 explanations correctly.

indeed I thought I could use my own names :slight_smile:

thanks

pls take a short look and tell me if im on the right track

I have this now in my customize.yaml



cover.global:         # global shading settings
    cloud_level: 50                       # cloude level under which there will be no shading
    prefer_awning: "false"                # prefere awning over roller shutter for shading, kills the roller shutter except for if the limits of the respective awning is active
    energy_safeing: "false"               # if true and outdoor temp below freezing, dawn and dusk will not be honored, all shutters open/close on 0° elevation, ecxept for catdoor
    automation_pause_time: "6"            # time the shading / shutter operation should be paused, globally or individually, for the pause feature.

cover.EG_kueche:      # individual window shading settings
    window_direction: 180             # direction the window is facing: default 180 = south
    azimuth_limit_low: 45             # lover deviation from window direction from which shading is required: default 45 (positive value, also its negative of the window!)
    azimuth_limit_high: 45            # upper deviation from window direction up to wich shading is required: default 45
    window_tilt: 0                    # deviation from vertical if e.g. roof window (a wall window is 0° deviation)
    window_height: 1000               # height of window in mm
    window_wall_thickness: 400        # width of wall including inside window sill in mm
    window_sun_strake:  100           # acceptable width of sun streaks (AWS) in mm
    window_min_elevation_shading_active: 10 # from which elevation onward shading is required
    roller_shutter_depth: 50          # depth of the shutter from outside wall
    roller_shutter_start_shading: 98  # start shading in % of roller shutter
    roller_shutter_full_shading: 5    # fully shaded in % of roller shutter
    roller_shutter_catdoor: 5         # shutter max close setting for cat door or to prevent lock out from terrace door
    roller_shutter_catdoor_time:      # fixed offset time to close the shutter (catch up with the others), if "" then it will never fully close, except by manuall operation.
    roller_shutter_catdoor_active: "false" # if ture, catdoor function is active, if not, normal opeartion will be executed.
    roller_shutter_max: 68            # formula needs to be build. from which elevation shading is no longer required because the wall itself provides shading
    window_awning: "false"                   # awing available for this window (prefere awning is a global setting), if true, roller shutter will not do any shading work.
    shading_paused: "false"           # can be true, false and time, time reativates after the time of automation_pause_time
    open_on_window_open: "false"               # false will prevent automatic window opening during closed roller shutter, true will rise the roller shotter to slotted if window is opened (false will not on manuel windows).

and this is the beginning of the ported script in sensors.yaml


# roller-shutter EG-Küche 
- platform: template
  sensors:
    cover.EG_kueche_shading_pos:
      value_template: >-
        {% set azimuth = states('sensor.test_sun_azimuth') | float(0) %} {# free #}
        {% set elevation = states('sensor.test_sun_elevation') | float(0) %} {# free #}
        {% set window_direction = states('sensor.cover.EG_kueche.window_direction') | float(0) %} {# free #}
        {% set azimuth_limit_low = states('sensor.cover.EG_kueche.azimuth_limit_low') | float(0) %} {# free #}
        {% set azimuth_limit_high = states('sensor.cover.EG_kueche.azimuth_limit_high') | float(0) %} {# free #}
        {% set roller_shutter_max = states('sensor.cover.EG_kueche.roller_shutter_max') | float(0) %} {# free #}
        {% if (window_direction - azimuth_limit_low) < azimuth < (window_direction + azimuth_limit_high) and elevation < roller_shutter_max %} >{#must also check for clouds and temp before setting s = ture#}
          {% set shading = "true" %}
        {% else %}
          {% set shading = "false" %}
        {% endif %}

if i understood it right the result in the sensors.yaml will be updated when ever one of the inputs change, and there fore the sensor cover.EG_keuche_shading_pos will resemble the position the shutter should be, i then could have an automation to actually move the cover every say 5 mins to the then current pos, so the house will move all at basically same time