Automatic blinds / sunscreen control based on sun platform

i tested it, but i always get a error

and my blueprint code

alias: Sonnenschutz - Wohnzimmer Automatisch
description: ""
use_blueprint:
  path: basbruss/cover_height_sun.yaml
  input:
    cover_entity:
      device_id: 55d960f40a449d4e7586a344e92fe3cd
    azimuth: 314
    max_height: 1.3
    default_height: 100
    change_threshold: 3

can you perhaps help @langestefan

You will need to use the entity_id instead of the device_id. Entity_id also adds the attributes to the dataset :wink:

1 Like

you are right, i think now it works, gives a way to disable the automation ?

for example when i want to control the cover manuall ?

You can add a manual override input_boolean as the blueprint supports both extra actions and conditions in the configurable action part

2 Likes

You can also just use the automation.turn_off service: Automation Services - Home Assistant

2 Likes

okay, then i missunderstand the Conditions in the blueprint, when i add a Condition , for example

condition: state entity_id: binary_sensor.someone_home state: "off"

the blueprint will not execute when the sensor state is “off” correct?

Hello there!

First, I want to say that this is really amazing work. Well done. Good job!

With the blueprint everything was working out of the box. Almost flawless and well, here I need a bit of asssistance.

On the east side of my house I have a big hill and for today every window on that side could have gone into the “normal state” (= cover 100% open) 2 hours earlier because there was no direct sunlight of this direction.
I read about the FOV angle, but it didn’t help (reduced it from 90° to 45°). So I’d need to finish the day at azimuth 284° instead of 305°.

Any chance to solve that problem?

Thanks,
naturnorbert

Hi.

Do you mean you have hill on the west side of your house? Otherwise I don’t understand the azimuth angle of 284°.

image

I think the FOV angle could be a bit more flexible. I think it would be nice to have the ability to set a tracking ‘window’ by defining right/ left azimuth and top/bottom elevation. Kind of like this:

Would have solve your problem?

Hi!

Yes.

I guess how I draw it it’s not like the FOV works. Currently I subtract on both sides of the window (like a cone), right?
So maybe it works somehow to just decide left/right/both from the view point inside house → outside window?

Does that make sense?

Greetings

Yes it is indeed a cone. The normal FOV would be 180°. You can also see it as half a circle from the point of view of the window.

I have simulated your drawing, now with independent upper and lower limits (azi_min and azi_max for the azimuth range). You can see nicely in the plot that it starts tracking when the sun moves from behind the window to in front of it at 13:00, and stops tracking at 20:00 when the azimuth exceeds 284°.

Would this work for you?

(do3esn’t exactly match your situation, but I hope you get the point? ps. I chose a random location in EU west)

1 Like

Yes, I guess that would be OK.

Wouldn’t it make sense to just give the Blueprint a condition where the user can set “between x and y do cover hight z%” + the option to recheck it every x minutes?
x, y should then maybe be the results out of your calculation to make it fit for summer and winter?

But just to be clear about the FOV:
image

So in my case if I rotate it just clockwise around the corner, I’d need to fill in “alpha” = 0° and “beta” = 90°. Maybe to script it that way is easier?

Edit:
If you want to I could prepare more data around my house. I control almost all of my windows (except childs sleeping room) with your blueprint.
Or can you maybe share the way you simulate it and I can recheck with my house if it fits?
Would that help?

Wouldn’t it make sense to just give the Blueprint a condition where the user can set “between x and y do cover hight z%” + the option to recheck it every x minutes?
x, y should then maybe be the results out of your calculation to make it fit for summer and winter?

That could work. However my experience with such rule based systems is that they solve the problem for a specific location and time of the year. What may work well in the summer may not work in the winter because the sun will be at a different elevation for the same azimuth.

So in my case if I rotate it just clockwise around the corner, I’d need to fill in “alpha” = 0° and “beta” = 90°. Maybe to script it that way is easier?

Your drawing is correct. There are basically two ways to define the tracking FOV. Reference North (0°) or the window (win_azi). I actually already do the second one to come up with valid angles in the first place:

# all angles above the horizon and within the half circle of the window facade
valid = np.logical_and((np.abs(gamma) < np.pi / 2), (alpha > 0))

# filter out sun azimuth outside azi_min and azi_max    
valid = np.logical_and(valid, ((sol_azi > azi_min) & (sol_azi < azi_max)))

So the final tracking range is thus the intersection of the half circle (as in your drawing) with the upper and lower limits defined by the user.

Here is the python code if you want to try the simulation yourself:

from pvlib import solarposition
import pandas as pd
import numpy as np
np.set_printoptions(suppress=True)
import matplotlib.pyplot as plt

tz = 'CET'
lat, lon = 52.35843822282988, 4.881058028007153

# summer
start_date = '2022-06-05'
end_date = '2022-06-06'

# winter
# start_date = '2022-12-05'
# end_date = '2022-12-06'

times = pd.date_range(start=start_date, end=end_date, freq='5min', tz=tz)
solpos = solarposition.get_solarposition(times, lat, lon)

# plot of elevation and azimuth
plt.figure(figsize=(15, 5))
solpos['elevation'].plot(label='elevation')
solpos['azimuth'].plot(label='azimuth')
plt.ylabel('Angle [°]')
plt.xlabel('Time [HH:MM]')
plt.legend()
plt.show()

from numpy import cos, tan, radians

def calculate_blind_height(sol_elev: float, sol_azi: float, win_azi, azi_min, azi_max, d: float) -> np.ndarray:
    """
    Calculate the height of the blind based on the sun position and the panel tilt and azimuth.

    :param sol_elev: elevation of the sun in degrees
    :param sol_azi: azimuth of the sun in degrees
    :param win_azi: azimuth of the panel in degrees from north
    :param win_tilt: tilt of the panel in degrees
    :param d: distance between the working area and window facade in meters
    """

    # surface solar azimuth
    gamma = radians(sol_azi - win_azi)

    # solar elevation
    alpha = radians(sol_elev)

    # all angles above the horizon and within the half circle of the window facade
    valid = np.logical_and((np.abs(gamma) < np.pi / 2), (alpha > 0))

    # filter out sun azimuth outside azi_min and azi_max    
    valid = np.logical_and(valid, ((sol_azi > azi_min) & (sol_azi < azi_max)))

    # calculate blind height
    return np.where(valid, (d / cos(gamma)) * tan(alpha), 0)

# variables
win_azi = 310
win_tilt = 0
h_max = 1.96
dis_workplane = 1
time = solpos.index

# azi min and max
azi_min = 90
azi_max = 284

# plot of blind height
ax, fig = plt.subplots(figsize=(12, 5))
plt.title(f"Window azimuth: {win_azi}°, azi_min: {azi_min}°, azi_max: {azi_max}°")
plt.plot(solpos['elevation'].values, label='elevation')
plt.plot(solpos['azimuth'].values, label='azimuth')

# two vlines, one at azi_min and one at azi_max
pos = np.where(np.logical_and(solpos['azimuth'].values > azi_min, solpos['azimuth'].values < azi_max))[0]
plt.vlines(pos[0], -10, 360, color='black', linestyle='--', linewidth=2, label='azi_min/azi_max')
plt.vlines(pos[-1], -10, 360, color='black', linestyle='--', linewidth=2 )
plt.xticks(np.arange(0, len(time), 12), time[::12].strftime('%H:%M'), rotation=90)
plt.ylabel('Angle [°]')
plt.xlabel('Time [HH:MM]')
plt.legend()

# plot of blind height
ax2 = fig.twinx()
blind_height = np.clip(calculate_blind_height(solpos['elevation'], solpos['azimuth'], win_azi, azi_min=azi_min, azi_max=azi_max, d=dis_workplane), 0, h_max)
ax2.plot(blind_height, label='blind height', color='red')

plt.ylabel('Blind height [m]')
plt.legend()
plt.show()
1 Like

Where do I find this line? My code is way shorter ? I dont want my covers to close to 0% fully to let some light in, a minimum of 15% woild be great.

My Automation looks like this:

alias: Auto Cover Height BĂźro
description: ""
use_blueprint:
  path: basbruss/cover_height_sun.yaml
  input:
    azimuth: 284
    distance: 0.1
    default_height: 100
    condition_on: true
    action_condition:
      - condition: state
        entity_id: input_boolean.automatikmodus_verschattung_buro
        state: "on"
    cover_entity:
      entity_id: cover.hmip_broll_2_00369f29974cf9_buero

Oh sorry that was before we had this nice blueprint. I need to add an option to set min percentage to the blueprint. Ps, the blueprint got updated yesterday so you don’t need an external sensor anymore to calculate the blind height.

1 Like

That would be absolutely awesome! Thanks in advance, i really enjoy this ! :slight_smile: Do you know, when you maybe have time to do the update?

The blueprint is now updated to include that variable. You can redownload the bleuprint to have acces to the feature you suggested. :smiley:

2 Likes

Wow, thats absolutely awesome!!! Thank you so so much! :slight_smile:

Whoops, this closes the cover Fully…
Anything I did wrong?

alias: Cover Height BĂźro Automatisch
description: ""
use_blueprint:
  path: basbruss/cover_height_sun.yaml
  input:
    distance: 0.1
    default_height: 100
    minimum_positon: 20
    cover_entity:
      entity_id: cover.hmip_broll_2_00369f29974cf9_buero
    action_condition:
      - condition: state
        entity_id: input_boolean.automatikmodus_verschattung_buro
        state: "on"
    condition_on: true
    azimuth: 253

And it also wont behave different, even if the switch is turned off.The automation still fires

is it possible to get the value that the blueprint sets the cover?
i want to send it to my handy over a notify, with the old method it was easy, there i used the state of the template sensor.

You can still use the template separately, calculations are not changed. The only thing different is that the blueprint supports the calculation without the sensor now.
Or you can use the variable cover_height in the notification action within the blueprint.

alias: Cover Height
description: ""
use_blueprint:
  path: basbruss/cover_height_sun.yaml
  input:
    cover_entity:
      entity_id: cover.rolgordijn_slaapkamer
    sun_sensor: sensor.cover_height_southside
    change_threshold: 6
    time_out: 10
    condition_mode: and
    condition_on: true
    action_condition:
      - condition: state
        entity_id: input_boolean.nacht_modus
        state: "off"
      - service: notify.mobile_app_iphone_van_bas
        data:
          message: "{{cover_height}}"
    azimuth: 186
    distance: 0.1
    max_height: 2.2
    default_height: 100
    degrees: 74

@4rctic I didn’t had time to test it could be a bug