Detecting strong(ish) sunlight

Bit of an interesting conundrum, but I’m sure there’s a simple solution…

My living room faces south-east (northern hemisphere), which means in the morning, if it’s sunny, I get a blast of sunlight for a good few hours which is enough to turn the living room into an oven by lunchtime. As such, I’m looking for a method of detecting such sunlight (or even better predicting if it will happen!), so I can turn my heating off - why burn energy when I have it for free coming in the window…

I initially tried simply using temperature and air pressure to try and forecast this - but that didn’t really work… especially since the effect happens in both summer and winter, so the external temperature fluctuates a fair bit.

My current thinking is to have some kind of sensor detecting whether there is sunlight hitting my window… perhaps sensing if the glass is heating up? I’m just not sure what I can use here, so any suggestions?

Just a note - my radiators are directly under my windows (because of course they are), so a simple temperature measurement is likely to be thrown off by radiant heat coming from them…

If you use a forecast that shows the cloud cover level then that could be used as a prediction of it happening.

True… I’m just sceptical of the accuracy given my location in Scotland :smiley:

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

I just tried with the API I use and Scotland doesn’t work. The error message says “You don’t need a forecast for this location, it’s always cloudy”

3 Likes

If you have motion sensors that also detect illuminance/LUX levels (or a weather station tied to HA), you could use LUX level changes to trigger an automation. I use outdoor motion sensors to average LUX levels, used to determine when presence sensors indoors will trigger lighting, and it works well. A single indoor sensor reporting lux should work for your needs.


I have a temp sensor outside. When sun hits it rises rapidly . You could have one in or outside and use the gradient to turn off your heating. In NI so similar climate.
I use this sensor to turn heating on earlier in cold mornings to get up to comfortable temp.

1 Like

This inspired me to give it a try.

Here is my first attempt:

alias: Element av vid solljus
description: ""
triggers:
  - trigger: template
    value_template: >-
      {{ state_attr('sensor.smhi_hourly', 'hourly')[now().timestamp() |
      timestamp_custom("%Y-%m-%d %H:")~"00"].tcc < 2 }}
    id: "on"
  - trigger: numeric_state
    entity_id:
      - sun.sun
    attribute: elevation
    above: 5
    id: "on"
  - trigger: template
    value_template: >-
      {{ state_attr('sensor.smhi_hourly', 'hourly')[now().timestamp() |
      timestamp_custom("%Y-%m-%d %H:")~"00"].tcc > 2 }}
    id: "off"
  - trigger: numeric_state
    entity_id:
      - sun.sun
    attribute: elevation
    below: 10
    id: "off"
conditions: null
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: >-
              {{ state_attr('sensor.smhi_hourly', 'hourly')[now().timestamp() |
              timestamp_custom("%Y-%m-%d %H:")~"00"].tcc < 2 }}
          - condition: numeric_state
            entity_id: sun.sun
            attribute: elevation
            above: 5
          - condition: trigger
            id:
              - "on"
        sequence:
          - action: climate.turn_off
            metadata: {}
            data: {}
            target:
              entity_id:
                - climate.david
                - climate.matilda
                - climate.sovrum
                - climate.vardagsrum
      - conditions:
          - condition: trigger
            id:
              - "off"
        sequence:
          - action: climate.turn_on
            metadata: {}
            data: {}
            target:
              entity_id:
                - climate.david
                - climate.matilda
                - climate.sovrum
                - climate.vardagsrum
mode: single

So when the cloud cover is less than 2/8 then it triggers, but also with sun above 5 degrees (I just guessed here)

You could just get an Aqara lux sensor or equivalent. Mount it where you want the sun intensity reading and use thresholds to trigger things. I do this for adjusting shades on a west facing window to reduce sun bleaching of furniture fabric. Works great.

We have had a few days with sun now and it seems the automation is working fine.

south and east facing rooms

north facing rooms

So the north facing rooms struggle a bit more but the temperature isn’t that bad