Bildquelle: www.zum.de/portal/
Azimut und Zenit
Mit diesen beiden Winkeln kann man den aktueleln Stand der Sonne von überall auf der Welt beschreiben:
- Azimut nennt man den Winkel der Sonnen zur Nord/Süd-Achse. Durch die Bestimmung des Azimut kann man also feststellen, von welcher Himmelsrichtugn die Sonne gerade scheint und z.B. prüfen, welches Fenster dadurch gerade bescheint wird und welches der Sonne gerade abgewandt ist.
- Der Zenit ist der Winkel der Sonne zur Senkrechten zum Erdmittelpunkt. Mithilfe der Zenit-Angabe kann man sehen, wie "hoch" die Sonne gerade steht. Im Sonner erreicht der Zenit erwartungsgemäß seht hohe Werte und im Winter steht die Sonne niedrig.
Diese beiden Zahlen kann man nach verschiedenen Methoden berechnen, die mehr oder weniger Präzise sind. Für die Anforderungen hier im hundhome sind aber alle Methoden gleichwertig genau. Alle Methoden erfordern darüber hinaus die Kenntnis der aktuellen Position auf dem Globus - also die Angabe des Längengrads und des Breitengrads. Schließlich ist der Stand der Sonne immer abhängig vom Ort an dem man sich befindet.
Zunächst habe ich im Internet nach Online Diensten gesucht, die eine API anbieten zur Berechnung. Am ende fand ich eine Formel und habe mich entschieden den Wert selbst zu berechnen und keine Online API zu nutzen. Ich erwarte, dass das am ende weniger zeitintensiv und systembelastend ist.
Die folgende LUA Funktion verwende ich:
moduleobj.calc = function(self, timestamp)
timestamp = timestamp or os.date("*t")
local dayofyear = (timestamp.month - 1) * 30.3 + timestamp.day
local declination = -23.45 * math.cos(sc.kbypi * 360 *(dayofyear + 10) / 365)
local timestate = 60 * (-0.171 * math.sin(0.0337 * dayofyear + 0.465) - 0.1299 * math.sin(0.01787 * dayofyear - 0.168))
local hourangle = 15 * ((timestamp.hour + timestamp.min / 60) - (15 - self.lon) / 15 - 12 + timestate / 60)
local sincenit = math.sin(sc.kbypi*self.lat)*math.sin(sc.kbypi * declination) + math.cos(sc.kbypi * self.lat) * math.cos(sc.kbypi * declination) * math.cos(sc.kbypi * hourangle)
local cenit = math.asin(sincenit) / sc.kbypi
local cosazimut = -(math.sin(sc.kbypi * self.lat) * sincenit - math.sin(sc.kbypi * declination)) / (math.cos(sc.kbypi * self.lat) * math.sin(math.acos(sincenit)))
local azimut = math.acos(cosazimut) / sc.kbypi
--if ((timestamp.hour + timestamp.min / 60) > (12 + (15 - self.lon) / 15 - timestate / 60)) then azimut = 360 - azimut end
return cenit, azimut
end
Die konstanten Zahlen in der Formel sind Vereinfachungen der Zahl Pi bzw. der Umrechnung vom Gradmaß zum Bogenmaß. Die Ungenauigkeit, die dadurch entsteht, ist für den hier gezeigten Anwendungsfall nicht kritisch. Die Werte des Längengrads und Breitengrads verbergen sich hinter den Variablen "self.lat" und "self.lon". Der Timestamp-Wert erlaubt es den Sonnenstand für eine bestimmte Tageszeit zu berechnen.
Die Integration in girder
Weil ich in girder die Veränderungen des Azimut und des Zenit Winkels als Event für Automatismen nutzen möchte, habe ich mich entschieden, die Berechnungsformel in einen virtuellen Sensor zu packen. Dieser Sensor liefert alle 5 Minuten den aktuellen Sonnenstand als eine JSON-Stuktur mit den beiden werten Azimut und Zenit.
Ein einzelnes item Manager Module Objekt bezieht sich dabei auf eine Lokation mit einem festen Längengrad und einem festen Breitengrad. Dazu wird ein einzelnes Item erstellt welches den virtuellen Sensor abbildet. Dieser Sensor gibt nun alle 5 Minuten einen JSON-String ab der im Rahmen von Regeln und Automatismen als Auslöser und Vergleichsoperator verwendet werden kann. In einem zukünftigen Beitrag erkläre ich, wie ich daraus eine Rollladensteuerung baue.