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):
tza_rad = math.radians(90.0 - solar_alt)
slope_rad = math.radians(obj_alt)
so_rad = math.radians((180 + obj_azm) % 360)
taa_rad = math.radians(solar_azm)
return math.degrees(
math.acos(
math.cos(tza_rad)
* math.cos(slope_rad)
+ math.sin(slope_rad)
* math.sin(tza_rad)
* math.cos(taa_rad - math.pi - so_rad)
)
)
# 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.