The script requires the `ephem` Python module. You need to install this where Indigo will have access to it.
I run this once a minute to update several variables in Indigo:
- solar_azimuth - current sun azimuth
- solar_altitude - current sun altitude
- solar_aoi_north - current AOI on north wall
- solar_aoi_south - current AOI on south wall
- solar_aoi_east - current AOI on east wall
- solar_aoi_west - current AOI on west wall
Near the bottom of the script, you'll notice a few hard-coded values (330, 60, 150, 240). These are the directions (in degrees) that each surface is facing. You'll want to update them for your application.
When checking this value in an action or trigger, you'll need to make sure that the sun is above the horizon for the AOI to make sense. Even though the trigonometry works out correctly, an angle below horizon isn't very useful for most applications. Also, if the AOI is greater than 90, it means that the sun is behind the intended surface.
Last point for now - you can also run this outside of Indigo and just pass your latitude / longitude as command line arguments. This may be useful for checking values before assigning to variables in Indigo.
- Code: Select all
import math
import ephem
import sys
try:
import indigo
(lat, lng) = indigo.server.getLatitudeAndLongitude()
has_indigo_host = True
except ImportError:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('lat', type=float)
parser.add_argument('lng', type=float)
args = parser.parse_args()
lat = args.lat
lng = args.lng
has_indigo_host = False
################################################################################
def set_attr(name, value):
if has_indigo_host:
indigo_var = indigo.variables.get(name, None)
if indigo_var is not None:
indigo.variable.updateValue(indigo_var, str(value))
else:
print(name + ' = ' + str(value))
################################################################################
# pysolar has a built-in method for AOI, however it doesn't run on Python 2
# so we kind of hijack it here for use in this script with mods for our needs...
# https://github.com/pingswept/pysolar/blob/master/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)))
################################################################################
obs = ephem.Observer()
obs.lat = str(lat)
obs.long = str(lng)
sun = ephem.Sun(obs)
solar_azm = math.degrees(sun.az)
solar_alt = math.degrees(sun.alt)
aoi_north = get_incident_angle(330)
aoi_east = get_incident_angle(60)
aoi_south = get_incident_angle(150)
aoi_west = get_incident_angle(240)
################################################################################
set_attr('solar_azimuth', solar_azm)
set_attr('solar_altitude', solar_alt)
set_attr('solar_aoi_north', aoi_north)
set_attr('solar_aoi_south', aoi_south)
set_attr('solar_aoi_east', aoi_east)
set_attr('solar_aoi_west', aoi_west)