Sensor to identify sun's entry into window - blind trigger

I have been trying to work out a formula that would give me data on when to close my blinds to stop the sun entering my living room… and I think I might have it.

After a refresher on high school trig and taking measurements of height, overhang and alignment with true north, Excel gave me a formula that looks right. I have modelled it in Fusion 360 and compared it to the handful of actual observations I have - and it looks pretty close. For example at azimuth 340-degrees, the sun needs to be lower than 58.8-degree elevation to enter. Today at azimuth 340 it was over 68-degrees elevation.

I then converted that to something for the configuration.yaml.

I have set up a new sensor that looks at the current azimuth and elevation and compares that with the elevation for the current azimuth that would allow the sun to enter my living room. It will countdown to zero - and then go negative. When the actual elevation is equal too the “entry” elevation for that azimuth, the sensor.suntriggerliving will have a numeric state of zero, so can be used to trigger the blinds to close.

This is the code I have placed in my configuration.yaml

  - sensor:
        name: SunTriggerLiving
        state_class: measurement
        icon: mdi:blind
        state: >
            {{(state_attr('sun.sun','elevation')) - (atan(2250/(650/(sin((pi/180)*(360 + 8.5 - (state_attr('sun.sun','azimuth')))))))*(180/pi))}}

(there might be too many brackets there - I will have to check)

KEY - just replace with your measurements

  • 2250 = distance vertically from bottom of the window to overhang
  • 650 = width (horizontal) of overhang from sun entry point
  • 8.5 = angle of window/wall from true north (in my case 8.5-degrees to the east of TN - would be negative if to the west)

I’m guessing in the northern hemisphere, the 360 would become 180???
I now have to work out the sensor to tell me when the sun has gone off my eastern facing window so I can have the blind open.


That’s clever! A great example of what you can do with HA.

Admittedly, I haven’t fully followed the math. A 'For Dummies" write-up would be interesting. I love it when astronomical calculations are used in practical solutions like this. Sort of like navigating; it requires a basic understanding of where you are on this planet. Something too many people are completely unaware of.

I hope my logic pans out - and maybe a person more skilled in maths can point out any error. You can also test the formula if you go to “Developer Tools” and “Template” in your HA instance.

It took me a while to realise, but after doing some modelling in Fusion, someone suggested trig would help. The Fusion drawings helped get it clear in my mind that I was dealing with two interconnected right-angled triangles - one horizontal and one vertical - sharing a common side.

The 1st drawing shows the azimuth (350°) - 10° off the true north line and the house is 8.5° to the east of true north. The first triangle (marked yellow) was created by the azimuth on the left and the window on the right. The base was formed by the width of the overhang - 650mm coming off the window until it intersects with the azimuth.

  • So now we know the length of one side (650mm) and an angle besides the 90 - 18.5° (10+8.5).

  • From there trig comes in and sin gives you the length of the hypotenuse - 2048.504mm. (650/sin(pi/180)*18.5).

Now we run a vertical line from where the base (650mm line) intersects with the azimuth line and take that up to the overhang which gives us the shadow/sunlight angle for that azimuth.

The hypotenuse (green highlight) of the horizontal triangle now becomes the base of vertical 90° triangle.

  • We know the length of two sides - the base (2048.504mm from above) and the vertical side (2250mm window to overhang).

  • Now using those two numbers, inverse tan (atan(2250/2048.504)*(180/pi)) gives us the angle from the bottom of the window to the point on the overhang at which sun would enter, for that azimuth. In this case (azimuth 350°) if the elevation is above 47.68°, the sun will not enter the window.

As the sun moves to the west and the azimuth decreases, the angle between the azimuth and house increases and the minimum elevation at which the sun will enter increases and vice versa. So in summer when the sun’s elevation is high, the sun’s azimuth will need to be closer to the west (ie a lower number) for the sun to enter. In winter, when the sun’s elevation is low, the sun will enter with a higher azimuth number.

I then look at the current elevation for the current azimuth and compare it to my calculation.

  • (state_attr(‘sun.sun’,‘elevation’) - calculation from above.

  • If the current elevation is above my calculated entry elevation (ie no sun enters), the sensor will have a positive number. If the current elevation is lower than my calculated elevation, (ie sun can enter) the sensor will be negative.

This will need azimuth tweaks for the northern hemisphere or if you want to work when the sun will be off a window on the eastern side.

The calculation for sun coming off my east side window is:

> {{(state_attr('sun.sun','elevation')) - (atan(2250/(1150/(sin((pi/180)*((state_attr('sun.sun','azimuth')-8.5))))))*(180/pi))}}

The overhang here is 1150mm and the trigger is when the number goes above zero.


Okay - over two months and my maths is holding up - the blinds open and close pretty much exactly when they need to.


I’m testing it in Spain. my window is facing west. now it’s winter and now I don’t need it, it seems to work well. I wait for the summer which is the time when I need it. Thank you


Did you have to change anything regarding the northern hemisphere?
Do you mind sharing the code for comparison?

Here is my example - completely untested, but for now it fits. :slight_smile:
House is tilted to the west (counterclockwise, northern hemisphere), window is facing roughly west:

{{((state_attr('sun.sun','elevation')) - (atan(1770/(1250/(sin((pi/180)*(360 +25 - (state_attr('sun.sun','azimuth')))))))*(180/pi)))|round(1)}}

I got my bearings from this website.

Basically making a line on the wall with the window - used the direction with the smaller value: 360 - bigger value and added this in the formula (+25). I did this for the north-ish side and added -90° for the west side.

After multiple tryouts, this needs still some validation.

Thanks for sharing this. I had a much simpler approach (azimuth an elevation separately) that worked, but this is perfect.

1 Like

Thanks for this @steve61!

I’m trying to integrate into my configuration.yaml but I get the following error message:

Failed to call service homeassistant/restart. The system cannot restart because the configuration is not valid: Invalid config for [sensor]: required key not provided @ data['platform']. Got None. (See /config/configuration.yaml, line 35).

Am I meant to add an entry for platform here?

Many thanks,

I have a bunch of these around my house. Which seem to work pretty well for figuring out light level in the room for automation purposes. Although not directly, I run their value through a statistics sensor to iron out some of spikes. I like your math though!

Make sure you are using it like this:

  - sensor:
    name: SunTriggerLiving
    state_class: measurement
    icon: mdi:blind
    state: >
            {{(state_attr('sun.sun','elevation')) - (atan(2250/(650/(sin((pi/180)*(360 + 8.5 - (state_attr('sun.sun','azimuth')))))))*(180/pi))}}

I use the following code. seems to work fine for 6 months

    friendly_name: Entrada_sol
    value_template: >
        {{(state_attr('sun.sun','elevation')) - (atan(2690/(1180/(sin((pi/180)*(360 + 33  - (state_attr('sun.sun','azimuth')))))))*(180/pi)) | round(2)}}

@davinci’s suggestion is the way I have it set up, along with the same format for a few other sensors (eg for reporting my solar PV output)

I am doing something fundamentally wrong I think, I have the value turning positive in the middle of the night, that should not happen no matter the window’s azimuth…

{{(state_attr('sun.sun','elevation') - atan(1330/(200/(sin( pi/180 * (state_attr('sun.sun','azimuth') + 143))))) * 180/pi) | round(1)}}

This turns positive around 3:35 AM, which should not be possible, as it’s still dark. The elevation and azimuth sensors seem to work fine, I am drawing them on separate cards and I cross referenced the values with a website.

The wall is facing north-east, hence the sun should only be hitting the window a couple of hours a day max, but the azimuth of the wall doesn’t matter actually, no window should see the sun at 3 in the morning. Something is completely wrong somewhere else.

Any idea what I missed?

The equation will return a “zero” every 12 hours. For example, today mine returned zero at about 11:20am and will again at 11:20pm, when the sun is on on the other side of the Earth:

You need to put a Condition after the trigger in your automation so that it only triggers in daylight. In my case, I just include a condition that says the trigger is only valid after sunrise and before sunset. This is my UI Condition which follows the Trigger:

You could just put a condition that says it can’t trigger before 07:00 or after 18:00 - or something similar

That condition is probably redundant on mine because I also have a condition that says if my solar PV is producing below a set amount of power, (ie it’s not sunny) leave the blind open. Clearly there’s not much power being produced at 11:20pm.

1 Like

Hope this isn’t hijacking this thread, but I also have a bunch of these light sensors - would you mind sharing more detail on how you smooth out their data with a statistics sensor? I got rather stumped looking at all the available options…

Sure np. This is what I’ve been running with recently:

- platform: statistics
  name: Bedroom illuminance lux stats
  entity_id: sensor.bedroom_light_sensor_illuminance_lux
  unique_id: 66116d54be8840678c4a12586dd32302_bedroom_illuminance
  state_characteristic: average_linear
  sampling_size: 10
    hours: 1

I won’t say this is perfect. It seems to work well during the day to recognize when clouds have made it dark enough that extra light is needed. As it trends towards night the number of samples is reduced. I lowered the number to 10 to help it recognize that its dark sooner but sometimes it still takes too long for my taste.

Another thing I would recommend is wrap these in a template binary sensor like “Bright bedroom” and check that to see if its bright or not. In that sensor put in a sun is down check like this:

{{ is_state('sun.sun', 'above_horizon')
  and states('sensor.bedroom_illuminance_lux_stats') | float > threshold }}

So you just assume its dark when the sun is down (or if the sun angle is low enough if you want it to assume this a little before sunset or after sunrise). This way when the number of samples drops drastically around sunset you never get stuck waiting for the number of samples to actually go to 0 before it realizes its dark just because it happened to get hit with some bright light directly really close to sunset. Also you generally don’t have to deal with unknown this way since that usually only occurs at night when the number of samples is actually 0 for long periods.

If you have more questions though I would recommend starting a different thread. These sensors do work well but I think light sensors in general are a bit challenging to incorporate into home automation due to fluctuations. I’m sure there’s plenty of room for improvement on my stuff too and would be interesting to get others thoughts.

1 Like

Ah, I get it. Ok, so the value turns positive at 3AM but the automation should only trigger when additionally the condition “sun has risen” is met. That works then, because since the window is north-east, it is hit by the sun rising.

Actually, I will instead set a condition “sun elevation > XX” because there are buildings around etc, hence the sun does not hit the blinds immediately at sunrise.

The equation takes care of the angle if you have entered your local measurements. All the condition is doing is telling HA to ignore the trigger if it occurs between sunset and sunrise.

yes, but after sunrise and before elevation=10, no sun can hit the blinds (yet) because of buildings on the other side of the road. The equation cannot account for this I assume.

Ahh - okay that makes sense. If the elevation is the same value all year, that is a simple fix.

I have an issue with two of my blinds with the sun setting. At certain times of the year, one blind is in shadow much sooner than the one next to it, because of the shape and alignment of our neighbour’s house. In the middle of summer, the setting sun comes off both blinds at the same elevation, but in winter there is an 8-degree difference.

not exactly, but close enough. I won’t 3D model the buildings around our street to build the trigonometric equation that models this. Your equation is already beyond what I remember from school.

There you go! AutoCAD, and a 10-lines trigonometric expression to model this =)

Or a solar sensor on the wall, that’s maybe even better, as it will take into account real time cloudiness.