# Yet Another Solar Calculator

Just wanted to pass along my take on a solar calculator… I use this mostly to manage blinds as the sun moves throughout the seasons. This solution is comprised of 3 parts: helpers, a script and automation events. This is mostly to keep discrete building blocks that are easy to use if I change methods in the future.

The Helpers are numbers (0-360) hold input values for each surface:

The python_script calculates the angle of incidence on a surface and updates a helper:

# lifted from pysolar - https://github.com/pingswept/pysolar/blob/4bb54dfe6e9ab79ea1a6a24bffb3e46cbeadc918/pysolar/solar.py
def get_incident_angle(obj_azm, obj_alt=90.0):

return math.degrees(
math.acos(
)
)

# expected input parameters
solar_azm = data.get('azimuth', None)
solar_alt = data.get('elevation', None)
obj_angle = data.get('angle', None)
entity_id = data.get('entity_id', None)

solar_aoi = get_incident_angle(obj_angle)

# update the helper value
logger.info('Update AOI %s => %d°', entity_id, solar_aoi)
hass.services.call('input_number', 'set_value', {
"value": solar_aoi,
"entity_id": entity_id,
}, False)

An automation, which calls the script every minute. This requires parameters with the sun’s azimuth & elevation as well as the angle of the object to compare and an input_number helper for the result. Of course, the sun’s values could be derived another way, such as a fixed time during the day.

alias: Sun - Calculate AOI
description: ''
trigger:
- platform: time_pattern
hours: '*'
minutes: '*'
seconds: '0'
condition: []
action:
- service: python_script.solar_aoi
data_template:
elevation: |
{{ states.sun.sun.attributes.elevation }}
azimuth: |
{{ states.sun.sun.attributes.azimuth }}
angle: 240
entity_id: input_number.solar_aoi_west_wall
mode: single

And of course the automations, which trigger on changes in the helpers:

alias: Sun - Afternoon - West Wall
description: ''
trigger:
- platform: numeric_state
entity_id: input_number.solar_aoi_west_wall
below: '60'
condition: []
action:
- device_id: b363fe5b059011eb9bd889653556d50b
domain: cover
entity_id: cover.office_blinds
type: set_position
position: 50
mode: single

To help find the best incident angle for taking action, I use the history for each helper to find out what the angle was at the time I wanted the blinds to close.

2 Likes