An bisherigen Ansätzen stört mich, dass der Zeitpunkt im einfachsten Fall "irgendwie" am Sonnenuntergan hängt, was zu einer jahreszeitlich notwendigen Anpassung führt. Funkleuchtturm hat das zwar hier (http://homematic-forum.de/forum/viewtop ... 8c03f66a14) mit einer Logik minimiert, aber auch hier müssen die richtigen Anpassungparameter erstmal gefunden werden. Andere Ansätze hängen sich an ganz andere Größen, wie z.B. Helligkeit (sofern man denn einen Sensor hat), was aber zu eigenen Problemen führt, z. B. bei Gewitter/Bewölkung am Abend.
Wenngleich keiner dieser Ansätze verkehrt ist, war mein Gedanke jedoch, dass der Dämmerungsverlauf doch ein strikt mathematisch beschriebener astronomischer Vorgang ist, der somit genau berechenbar ist. Klar, diese Berechnung ist nicht ganz einfach, andererseits gibt es zahlreiche Websites, auf denen die einzelnen Dämmerungszeitpunkte pro Geoposition nachgeschaut werden können. Somit braucht man also nur einen Script, der die Werte auf die CCU holt und sie mit einem Parameter "anpassbar" macht.
Zum Nachbauen empfiehlt es sich dringend, die Dokumentation auf http://de.wikipedia.org/wiki/D%C3%A4mmerung, http://lexikon.astronomie.info/zeitgleichung/ und http://www.calsky.com zu studieren, insbesondere die Unterschiede zwischen Sonnenuntergang, Bürgerlicher Dämmerung, Nautische Dämmerungn und Astronomischer Dämmerung.
Funktionsweise:
Der HM-Script "AstroDatenHolen" läuft einmal pro Nacht, ruft über CUxD den Shellscript "GetAstroDates.sh" mit den Positionsangaben aus der WebUI auf und schreibt die aus der Web-Antwort ausgelesenen Dämmerungszeiten in die Systemvariablen. Dann berechnet es anhand des eingestellten Ausgangszeitpunkts und des Prozentwertes den finalen Rolladen-Zeitpunkt und programmiert den Timer zu dieser Zeit (auf dessen Auslösen wiederum die Rolläden runter fahren).
Als Ausgangswert kann man "Sonnenuntergang + 50%" nehmen, was also die Mitte zwischen "Sonnenuntergang" und "Ende Bürgerlicher Dämmerung" darstellt (wenn der Dämmerungskamm den Zenit durschreitet) und logischerweise jeden Tag in einer anderen Zeit mündet. Wer es auf die Spitze treiben möchte, kann diesen Prozentwert noch von einem Helligkeitssensor beeinflussen lassen, vom Regensensor, oder vom gemeldeten Bewölkungsgrad eines Wetterdienstes...
Voraussetzungen:
- Der SSH-Zugang auf der CCU2 muss aktiviert sein.
- CUxD muss installiert sein.
- In der WebUI unter "Einstellungen - Systemsteuerung - Zeit-/Positionseinstellung" muss die richtige Position eingetragen sein. Dieser Wert wird für die Abfrage der Daten von calsky.com verwendet.
- im CUxD ein "(28) System-Exec" Gerät mit der Seriennummer 1 anlegen
- im CUxD ein "(28) System-Timer" Gerät mit der Seriennummer 1 und Namen "TriggerRolladen" anlegen
- Systemvariablen für die Website-Werte anlegen (alle Zeichenkette):
- Sonnenaufgang
- Sonnenuntergang
- BeginBuergDaemm
- EndBuergDaemm
- BeginNautDaemm
- EndNautDaemm
- Tageslaenge
- BeginAstroDaemm
- EndAstroDaemm
- Systemvariablen für die Steuerung anlegen:
- RolladenZP (Zeichenkette): Dynamisch errechneter Zeitpunkt, nur zur Info
- RolladenzeitpunktBasis (Zeichenkette): Name der obigen Variable, die als Ausgangszeitpunkt für die Rolläden dienen soll. (z.B. "EndBuergDaemm")
- RolladenzeitpunktAnpassung (Zahl -100/100): Prozentwert, um den der Rolladenzeitpunkt in Richtung des nächsten (oder vorherigen) Zeitpunkts verschoben werden soll. Dabei ist "100%" identisch mit dem nächsten (vorherigen) Zeitpunkt.
Beispiel: Sonnenuntergang = 17:46, EndBuergDaemm = 18:10, Rolladenzeitpunkt = "Sonnenuntergang", RolladenzeitpunktAnpassung = 50%
Somit wird auf die Sonnenuntergangszeit (17:46) die Hälfte der Zeitspanne zu EndBuergDaemm draufgeschlagen, die Rolläden fahren also um 17:58 runter.
- Ein "Rolladen runter" Programm erstellen, das alle Rolläden zum Timer_Event des CUxD-Timers runterfährt, oder um 22:30 (oder wann auch immer). Letzteres dient quasi als Cut-off-Zeit, wenn der dynamische Dämmerungspunkt im Hochsommer noch später sein sollte. (siehe angehängter Screenshot)
- per SSH "GetAstroDates.sh" erstellen (unter /usr/local/):
Code: Alles auswählen
#!/bin/bash if [ $# -lt 2 ]; then echo "Fehlerhafter Aufruf!" echo "Es müssen 2 Parameter übergeben werden, der Erste ist der Längengrad, der Zweite der Breitengrad:" echo "z. B. ./GetAstroDates.sh 8:12:34.35698 50:12:34.13711" fi wget -q --header="User-Agent: Mozilla" "http://www.calsky.com/cs.cgi/Sun/2?lang=de&showtwilight=true&hideglos=true&dateNow&lon=${1}&lat=${2}" -O - | sed -e 's/[<]/\n&/g;s/ //g;/class="caltab"/,/<\/table>/!d' | sed -e 's/\(<b>\|<tt>\)//g;/\(Aufgang\|Untergang\|Begin\|Morgen\)/!d;s/\(Ende\|Abend\|Tag\)/\n&/g' | sed -e ':a;N;$!ba;s/\n/;/g;s/ //g;s/:/-/g;s/h/:/g;s/m//g;s/ ;/;/g'
- HomeMatic-Script "AstroDatenHolen" erstellen und auf tägliche Ausführung um 1:30 programmieren:
Code: Alles auswählen
! Diese Werte an den persönlichen Geschmack anpassen var RollZeit1 = "Sonnenuntergang"; var RollProz = 50.0; var cmd; var Return; string Tmp; real val; var Long; var Lat; var Rest; var Grad; var Min; var Sek; var Hdstl; var RollZeit2; var Rolladenzeit; var Index = 0; var Found; ! GeoPosition auslesen und in Dezimal nach Grad, Min, Sek umwandeln Grad = 1 * system.Longitude(); Rest = system.Longitude() - Grad; Min = 1 * Rest * 60; Rest = (Rest * 60) - Min; Sek = 1 * Rest * 60; Rest = (Rest * 60) - Sek; Hdstl = 1 * Rest * 100; Long = Grad # ":" # Min # ":" # Sek # "." # Hdstl; Grad = 1 * system.Latitude(); Rest = system.Latitude() - Grad; Min = 1 * Rest * 60; Rest = (Rest * 60) - Min; Sek = 1 * Rest * 60; Rest = (Rest * 60) - Sek; Hdstl = 1 * Rest * 100; Lat = Grad # ":" # Min # ":" # Sek # "." # Hdstl; ! Befehl zusammenbauen cmd = "/usr/local/GetAstroDates.sh " # Long # " " # Lat; ! Befehl ausführen: Werte von Website holen dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(cmd); dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1); Return = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State(); ! Werte auslesen und in Systemvariablen schreiben Tmp = Return.StrValueByIndex(";",0).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("Sonnenaufgang").State(Tmp); Tmp = Return.StrValueByIndex(";",1).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("Sonnenuntergang").State(Tmp); Tmp = Return.StrValueByIndex(";",2).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("BeginBuergDaemm").State(Tmp); Tmp = Return.StrValueByIndex(";",3).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("EndBuergDaemm").State(Tmp); Tmp = Return.StrValueByIndex(";",4).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("BeginNautDaemm").State(Tmp); Tmp = Return.StrValueByIndex(";",5).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("EndNautDaemm").State(Tmp); Tmp = Return.StrValueByIndex(";",6).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("Tageslaenge").State(Tmp); Tmp = Return.StrValueByIndex(";",7).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("BeginAstroDaemm").State(Tmp); Tmp = Return.StrValueByIndex(";",8).StrValueByIndex("-", 1); if (Tmp.Find(".") > -1) {; val = "0." # Tmp.StrValueByIndex(".", 1); val = "0" # val.ToFloat() * 60; Tmp = Tmp.StrValueByIndex(".", 0) # ":" # val.Substr(val.Find(".") - 2, 2); } dom.GetObject("EndAstroDaemm").State(Tmp); ! schreibe Rolladen-Konfiguration dom.GetObject("RolladenzeitpunktBasis").State(RollZeit1); dom.GetObject("RolladenzeitpunktAnpassung").State(RollProz); ! finde Variable für RollZeit1 RollZeit2 = "Sonnenuntergang,EndBuergDaemm,EndNautDaemm,EndAtroDaemm,BeginAtroDaemm,BeginNautDaemm,BeginBuergDaemm,Sonnenaufgang"; foreach(Tmp, RollZeit2.Split(",")) {; if (Tmp == RollZeit1) {; Found = Index; } else {; Index = Index + 1; } } ! bestimme Variable für RollZeit2 if (RollProz < 0) {; RollZeit2 = RollZeit2.StrValueByIndex(",", Found - 1); } else {; RollZeit2 = RollZeit2.StrValueByIndex(",", Found + 1); } ! Zeiten einlesen RollZeit1 = dom.GetObject(RollZeit1).Variable(); RollZeit2 = dom.GetObject(RollZeit2).Variable(); RollZeit1 = system.Date("%F") # " " # RollZeit1; RollZeit1 = RollZeit1.StrValueByIndex(".", 0); RollZeit1 = RollZeit1.ToTime().ToInteger(); RollZeit2 = system.Date("%F") # " " # RollZeit2; RollZeit2 = RollZeit2.StrValueByIndex(".", 0); RollZeit2 = RollZeit2.ToTime().ToInteger(); ! finale Zeit berechnen if (RollProz < 0) {; Rolladenzeit = RollZeit1 + (0.0 + RollZeit1 - RollZeit2) * RollProz / 100.0; } else { Rolladenzeit = RollZeit1 + (0.0 + RollZeit2 - RollZeit1) * RollProz / 100.0; } ! Zeit speichern und Timer setzen Rolladenzeit = Rolladenzeit.ToTime().Format("%T"); dom.GetObject("RolladenZP").State(Rolladenzeit); dom.GetObject("CUxD.CUX2800001:1.TIMER_SET").State(Rolladenzeit);
- Freuen...
Linuzer
PS: Ich werde hier im ersten Post die Änderungen/Fehlerkorrekturen aus dem Thread einpflegen, sodass hier immer die aktuellste/richtige Version steht.
Update 25.02.2014:
Wenn einstellige Sekunden von der Website gemeldet wurden, wurden die Werte nicht korrekt verarbeitet.
Update 07.05.2014:
- GetAstroDates.sh aktualisiert
- Pfad für GetAstroDates.sh ("usr/local/") harmonisiert (Punkt 6 der Anleitung und Aufruf im Script; Es ist egal, wo es steht, nur müssen die Pfade übereinstimmen)
- Variablenname "RolladenZP" harmonisiert
- Variablenname "EndAstroDaemm" und "BeginAstroDaemm" Rechtschreibfehler korrigiert