Astral – mit Python Sonnenaufgang, Sonnenuntergang, Mondphasen, goldene / blaue Stunde berechnen
Bei meinen Experimenten, den Raspberry Pi bei Sonnenaufgang und Sonnenuntergang etwas tun zu lassen, hat ein Kommentator die Python-Bibliothek Astral erwähnt. Damit würde es auch offline funktionieren. Ich bin schon vorher darüber gestolpert, aber es funktionierte nicht so richtig. Allerdings hat mich die Idee auch nicht losgelassen und ich wollte mich genauer mit Astral beschäftigen. Ich programmiere nicht so oft und einfach war das nicht, muss ich zugeben.
Eines meiner größten Probleme war, dass sich die meisten Beispiele für Astral im Web auf Python 2 beziehen und nicht Python 3. Es gibt noch ein paar andere Stolpersteine, über die ich gefallen bin. Der Beitrag hier soll auch als persönlicher Spickzettel dienen. Es ist einfach eine Installationsanleitung mit ein paar Fallbeispielen in Scripten. Die offizielle Dokumentation arbeitet nur mit der Python-Shell und ist meiner Meinung nach nicht sehr anfängerfreundlich. Außerdem hat sich herausgestellt, dass die Dokumentation zu Astral etwas undurchsichtig. Die perfekte Zutat für Frust.
Ein Wort zu offline: Der Raspberry Pi hat per Standard keine RTC (Real Time Clock) und speichert die Uhrzeit deswegen nicht dauerhaft. Willst Du bei Systemstart die korrekte Uhrzeit haben, muss der Pi online sein. Du kannst die Uhrzeit auch manuell stellen oder lötest ein RTC-Modul an*.
Übrigens: Die Berechnungen mit Astral unterscheiden sich nur minimal zu meiner Online-Lösung. Deswegen habe ich mein Script auch angepasst und benutze nun eine Offline-Variante. In der Dokumentation steht, dass die Höhe des Standorts nicht in die Berechnung einfließt, weil es vernachlässigbar ist.
Probleme mit Astral und Raspberry Pi
Ausgangspunkt war eine komplett neue Installation von Raspbian Buster, die auf den neuesten Stand gebracht wurde:
sudo apt update sudo apt upgrade
Da Astral via Pip installiert wird, müssen wir das entsprechende Paket für Python 3 installieren
sudo apt install python3-pip
Die offizielle Dokumentation beschreibt dann auch noch, wie ich Astral installieren kann:
pip3 install astral
Der Anfang ist gemacht und die Software ist installiert.
Weil bei Raspbian Lite im Gegensatz zur Desktop-Version gpiozero nicht installiert ist, erledige ich das an dieser Stelle auch gleich. Will ich Dinge via Astral schalten, brauche ich das früher oder später.
sudo apt install python3-gpiozero
Nun bin ich mit den Vorbereitungen zufrieden.
Script fällt auf die Nase
Nun habe ich gleich versucht, Astral in einem Script zu benutzen und das ist grandios auf die Nase gefallen. Das war damals auch der Grund, warum ich es nicht weiter benutzt habe. Mein Fehler war, das Test-Script astral.py zu nennen und deswegen ist das Script auf die Nase gefallen. Ich habe diese Fehlermeldung erhalten:
ImportError: cannot import name ‘LocationInfo’ from ‘astral’ (/home/pi/astral.py)
Hier als Screenshot:
Spielst Du mit dem Programm, dann mache einfach nicht den gleichen Fehler wie ich. Benenne ich die Datei in astral_test.py um, funktioniert die Sache. Man lernt nie aus.
Aber genug der Probleme. Sehen wir uns nun ein paar praktische Beispiele an. Das macht auch wesentlich mehr Spaß.
Datenbank von Astral abfragen
Aus der Dokumentation kannst Du entnehmen, dass Standortdaten für diverse Städte in einer Datenbank vorhanden sind. Es sind alle Hauptstädte, plus ein paar zusätzliche Städte aus Großbritannien und den USA enthalten. Die einzige deutsche Stadt mit Standortdaten ist somit Berlin. Du kannst die Datenbank wie folgt abfragen:
from astral import LocationInfo from astral.geocoder import database, lookup city = lookup("Berlin", database()) print(city)
Damit bekomme ich folgende Ausgabe:
Ich kann die Werte auch einzeln abfragen:
from astral import LocationInfo from astral.geocoder import database, lookup city = lookup("Berlin", database()) print(city.name) print(city.region) print(city.timezone) print(city.latitude) print(city.longitude)
Ich muss die Datenbank aber nicht benutzen, sondern kann meinen eigenen Standort definieren. Dafür muss ich natürlich astral.geocoder nicht mehr importieren. Willst Du die Berechnung so genau wie möglich haben, definierst Du am besten Breitengrad und Längengrad selbst:
from astral import LocationInfo city = LocationInfo(name="Regensburg", region="Germany", timezone="Europe/Berlin", latitude=49.03451, longitude=12.11923) print(( f"Information for {city.name}/{city.region}\n" f"Timezone: {city.timezone}\n" f"Latitude: {city.latitude:.02f}; Longitude: {city.longitude:.02f}\n" ))
OK, nun haben wir unseren Standort definiert. Schauen wir uns an, was wir damit machen können.
Sonnenaufgang, Sonnenuntergang, Morgendämmerung und Abenddämmerung
Mit dem Standort berechnet uns Astral die gewünschten Zeiten, per Standard in UTC. Das ist relativ einfach und sieht wie folgt aus:
from astral import LocationInfo from astral.sun import sun city = LocationInfo(name="Regensburg", region="Germany", timezone="Europe/Berlin", latitude=49.03451, longitude=12.11923) c_data = sun(city.observer) print("Sonnenaufgang: " + str(c_data["sunrise"])) print("Sonnenuntergang: " + str(c_data["sunset"])) print("Morgendämmerung: " + str(c_data["dawn"])) print("Abenddämmerung: " + str(c_data["dusk"]))
Die Ausgabe ist wie folgt:
Hinweis: Die Zeiten werden berechnet, wenn die Sonne den Horizont bei klarer Sicht durchbricht – Hindernisse im Auge des Betrachters werden nicht beachtet.
Gibst Du kein Datum an, rechnet Astral mit dem aktuellen Datum. Du kannst Dir die Werte aber auch für ein bestimmtes Datum berechnen lassen. Du musst es bei der Definition von c_data nur angeben und datetime importieren. Hier ein Beispiel für den 21. Oktober 2019:
from astral import LocationInfo from astral.sun import sun import datetime city = LocationInfo(name="Regensburg", region="Germany", timezone="Europe/Berlin", latitude=49.03451, longitude=12.11923) c_data = sun(city.observer, date=datetime.date(2019, 10, 21)) print("Sonnenaufgang: " + str(c_data["sunrise"])) print("Sonnenuntergang: " + str(c_data["sunset"])) print("Morgendämmerung: " + str(c_data["dawn"])) print("Abenddämmerung: " + str(c_data["dusk"]))
Da sind die Tage schon kürzer:
In der Dokumentation steht, dass man sich auch Informationen zur goldenen Stunde und blauen Stunde anzeigen lassen kann. Vor allen Dingen für Fotografen sind das wichtige Informationen.
Goldene Stunde und blaue Stunde
Die blaue Stunde und die goldene Stunde tauchen zweimal pro Tag auf. Vereinfacht gesagt: bei der blauen Stunde steht die Sonne unterhalb des Horizonts und bei der goldenen knapp drüber. Bei der blauen Stunde dominiert das blaue Lichtspektrum und bei der goldenen Stunde sind die Farben viel weicher und wärmer.
Das Problem an dieser Stelle ist, dass nicht offensichtlich in der Dokumentation steht, wie ich an diese Werte komme. Nun könnte ich an dieser Stelle raten oder besser einen Blick in die entsprechende Datei werfen, die zum Glück auf GitHub frei verfügbar ist.
Du findest es auch in der Dokumentation, wenn Du auf Package klickst. Das ist etwas versteckt und ich mag Dokumentationen nicht, bei denen man Ostereier suchen muss.
Im Gegensatz zum Sonnenaufgang oder Sonnenuntergang haben blaue Stunde und goldene Stunde zwei Werte: Anfang und Ende. Gibst Du keinen zusätzlichen Wert an, rechnet Astral per Standard zur aufgehenden Sonne. Lassen wir uns die Daten ausgeben:
from astral import LocationInfo from astral.sun import golden_hour from astral.sun import blue_hour city = LocationInfo(name="Regensburg", region="Germany", timezone="Europe/Berlin", latitude=49.03451, longitude=12.11923) gh = golden_hour(city.observer) bh = blue_hour(city.observer) print("Goldene Stunde Start: " + str(gh[0])) print("Goldene Stunde Ende: " + str(gh[1])) print("Blaue Stunde Start: " + str(bh[0])) print("Blaue Stunde Ende: " + str(bh[1]))
Die Berechnung für den Morgen sieht dann so aus:
Möchte ich die goldene Stunde und die blaue Stunde für den Abend berechnen, muss ich die Richtung der Sonne auf SETTING setzen. RISING gibt es auch, aber das ist der Standard, wie schon angesprochen. Möchte ich das berechnen, sieht der Code zum Beispiel wie folgt aus (goldene Stunde am Abend und blaue Stunde am Morgen).
from astral import LocationInfo from astral.sun import SunDirection from astral.sun import golden_hour from astral.sun import blue_hour from datetime import datetime city = LocationInfo(name="Regensburg", region="Germany", timezone="Europe/Berlin", latitude=49.03451, longitude=12.11923) gh = golden_hour(city.observer, datetime.now().date(), SunDirection.SETTING) bh = blue_hour(city.observer) print("Goldene Stunde Start: " + str(gh[0])) print("Goldene Stunde Ende: " + str(gh[1])) print("Blaue Stunde Start: " + str(bh[0])) print("Blaue Stunde Ende: " + str(bh[1]))
Das Ergebnis liest sich wie folgt:
Du siehst an den Zahlen auch, dass die goldene Stunde und die blaue Stunde nicht wirklich 60 Minuten sind. Es kommt hier sehr auf Standort und Jahreszeit an. Deswegen ist es gut zu wissen, wann Du mit Deiner Kamera auf Zack sein musst.
Wir können uns mit Astral übrigens auch Informationen zum Mond ausgeben lassen.
Mit Astral Mondphasen berechnen
Das Tool kann auch die Mondphasen ausgeben. Anhand des Datums spuckt das Python-Programm eine Zahl zwischen 0 und 28 aus. In der Dokumentation finden wir, wie die Zahlen der Mondphasen zu deuten sind:
- 0 – 6,99 – Neumond
- 7 – 7,99 – zunehmender Mond
- 14 – 20,99 – Vollmond
- 21 – 27,99 – abnehmender Mond
Damit die Sache etwas spannender wird, lassen wir uns die Mondphase von gestern, heute und morgen anzeigen. Vor allen Dingen der folgende Tag ist sinnvoll, wenn Du zum Beispiel wissen willst, wann der Mond am vollsten ist:
from astral.moon import phase import datetime moon_today = phase() moon_yesterday = phase(datetime.datetime.now() - datetime.timedelta(days=1)) moon_tomorrow = phase(datetime.datetime.now() + datetime.timedelta(days=1)) print("Mond gestern", end=": ") print(moon_yesterday) print("Mond heute", end=": ") print(moon_today) print("Mond morgen", end=": ") print(moon_tomorrow)
Astral würde nun folgendes ausgeben:
Nun kann man damit lustige Spielchen machen. Willst Du zum Beispiel Sterne fotografieren, willst Du so wenig Mond wie möglich haben.
Mit nachfolgendem Script finden wir zum Beispiel heraus, wann der Mond in den nächsten 365 Tagen am vollsten und am wenigsten sichtbar ist:
from astral.moon import phase import datetime moon_dic = {} for var in list(range(365)): date_temp = datetime.datetime.now().date() + datetime.timedelta(days=(var)) moon_phase = phase(date_temp) moon_dic[moon_phase] = date_temp darkest = min(moon_dic) print(moon_dic.get(darkest), end=": ") print(darkest) darkest2 = max(moon_dic) print(moon_dic.get(darkest2), end=": ") print(darkest2)
Nun weiß ich, dass in den nächsten 365 Tagen der Mond am 17. September 2020 und am 11. Mai 2021 am sehr wenig sichtbar ist.
Wann er am vollsten ist, kann ich nicht genau sagen. Das Tool sagt mir, dass zwischen 14 – 20,99 Vollmond ist – aber nicht genau, wann der Mond am vollsten ist. Ist das genau bei der Hälfte, also 14? Ich werde in den Himmel starren und versuchen, das beim nächsten Vollmond selbst herauszufinden.
Update: Der vollste Vollmond ist bei 14. Das war der Vollmond gestern Nacht (5. Juni 2020) bei 13,6.
Hier die Astral-Ausgabe zum Screenshot oben. Nun bin ich schlauer und meine anfängliche Vermutung hat sich bestätigt.
Das Tool kann noch ein paar andere Daten berechnen, aber mehr brauche ich im Moment nicht. Ich kann ausrechnen, was ich will und mir die Daten auch auf mein Smartphone schicken lassen (mit Pushover).
Nun hab ich einen eigenen Bitcoin Ticker, einen Coronavirus Ticker und ein Tool für Sonnenaufgang, Sonnenuntergang, blaue Stunde, goldene Stunde und Mondphasen. Ich weiß, dass es dafür verschiedene Apps gibt, aber ich muss weniger Zeug auf meinem Smartphone installieren und kann mir die Tools außerdem so anpassen, wie ich das gerne hätte. Nun kann ich mir aber sehr gezielt Informationen schicken lassen.
Ich hoffe, das war verständlich
Den Beitrag habe ich geschrieben, um Astral auch selbst ein bisschen besser zu verstehen. Ein paar Dinge sind mir noch nicht ganz klar, aber im Großen und Ganzen verstehe ich, wie Astral einzusetzen ist.
Vielleicht hilft Dir der Beitrag auch, etwas Sinnvolles mit dem Tool anzufangen. Nachdem ich kapiert habe, wie ich es benutze, finde ich es richtig gut. Auf jeden Fall gibt es jede Menge Möglichkeiten, wie sich die von Astral berechneten Daten einsetzen lassen.
Nette Pi-Konstellation
Suchst Du ein VPN für den Raspberry Pi? NordVPN* bietet einen Client, der mit Raspberry Pi OS (32-Bit / 64-Bit) und Ubuntu für Raspberry Pi (64-Bit) funktioniert.