Schlagwort-Archive: Zeitsteuerung

Astro

ioBroker Astro-Tageszeit abfragen und in Datenpunkt eintragen

In ioBroker kannst Du mit den Astro Funktionen eine ganze Menge abfragen. Aber jede Astrozeit immer in jedem Skript abzufragen ist lästig, oder? Richtig! Mit diesem Skript kannst du global alle Werte der Astro Funktion abfragen und in passenden Datenpunkten abspeichern. Das Skript erstellt beim ersten Aufruf automatisch die benötigten Datenpunkte und sollte im common Bereich erstellt werden. Der Aufruf des Skripts geschieht alle 30 Minuten automatisch und kann in der letzten Zeile angepasst werden.
Hier kann es natürlich vorkommen, das die ein oder andere Tageszeit übersprungen wir, da sie nur 2-5 Minuten (gerade im Sommer: Sonnenauf- und untergang innerhalb von 5 Minuten) auseinander liegen. Zusätzlich gibt es 6 Variablen, die den aktuellen Astro – Zustand anzeigen (tageszeitAstro, naechsteTageszeitAstro, tageszeitLesbar, naechsteTageszeitLesbar, aktuelleAstroZeit, Tag). Die Variable Tag steht zwischen Sonnenauf- und untergang auf Tag.

Extra: Bei jedem Durchlauf des Skriptes wird überprüft, ob die eingetragene Uhrzeit bereits vergangen ist. Wenn ja, wird hier schon der Wert für die nächste Zeit dieses Ereignisses gespeichert. Auch bekommst du im Log immer eine Übersicht, wie der aktuelle Durchlauf des Skriptes abgelaufen ist.

Screenshot der verfügbaren Variablen

Screenshot der verfügbaren Variablen
Screenshot der verfügbaren Variablen

Ausgabe im Log

Log-Ausgabe
Log-Ausgabe

Skript

// Astro Zeiten erstellen
// Datenpunkte neu erstellen
var ueberschreiben = false;

// Hauptdatenpunkt unterhalb javascript
var datenpunkt = "Astro.";

// Lesbare Zeiten
const lesbare_zeiten = ["Früher Morgen","Frühe Dämmerung","Morgendämmerung","Sonnenaufgang","Vormittag","später Vormittag","Mittag",
                    "früher Abend","Abend","Sonnenuntergang","Abenddämmerung","später Abend","Nacht","Mitternacht"];

// Objekte der Astro Zeiten
const objekt = ["nightEnd","nauticalDawn","dawn","sunrise","sunriseEnd","goldenHourEnd","solarNoon","goldenHour",
            "sunsetStart","sunset","dusk","nauticalDusk","night","nadir","tageszeitAstro","naechsteTageszeitAstro",
            "tageszeitLesbar","naechsteTageszeitLesbar","aktuelleAstroZeit","Tag"];

// Zustände der Astro-Zeiten
const beschreibung = ["00 - Ende der Nacht","01 - nautische Morgendämmerung","02 - Morgendämmerung","03 - Sonnenaufgang",
            "04 - Ende des Sonnenaufgangs","05 - Ende der goldenen Stunde VM","06 - Mittag", "07 - goldene Abendstunde",
            "08 - Start des Sonnenuntergangs","09 - Sonnenuntergang","10 - Dämmerung Abends","11 - nautische Dämmerung abends",
            "12 - Start der Nacht","13 - Mitternacht","Aktuelle Tageszeit (Astro)","Nächste Tageszeit (Astro)", 
            "Aktuelle Tageszeit (lesbar)","Nächste Tageszeit (lesbar)","aktuelle Astrozeit","Solange die Sonne scheint, ist Tag"];

// Erstelle die benötigten Datenpunkte
function datenpunkte_erstellen() {
    for(var i = 0; i < objekt.length; i++) {
        createState(datenpunkt+objekt[i], "", ueberschreiben, {
        name: beschreibung[i],
        desc: beschreibung[i],
        type: "string",
        role: "value",
        unit: ""
        });
    }
    log("Astro: Datenpunkte erstellt!");
}

// Datenpunkte mit erstem Inhalt füllen
function datenpunkte_fuellen() {
    for (var i = 0; i < objekt.length-6; i++) {
        var datum = new Date();
        var astro_zeit = zeit_formatieren(getAstroDate(objekt[i], datum));
        if (astro_zeit=="Invalid Date") {
            astro_zeit = "00:00";
        }
        setState(datenpunkt+objekt[i], astro_zeit);
    }
    log("Astro: Erste Datenpunkte gefüllt!");
}

// Haupt-Skript
function update_astro_zeiten() {
    var datum = new Date();
    var uhrzeit = zeit_formatieren(datum);

    // Zustand der Daten
    var aktuell = 0;
    var aktualisiert = 0;
    var keine_aktualisierung = 0;
    var astro_index = 0;

    // Aktuellen Tagesabschnitt bestimmen
    var ergebnis = -1;
    var naechste_element = false;

    // Aktuelle & kommende Tageszeit
    var aktuelle_tageszeit = 0;
    var kommende_tageszeit = 0;

    // Tag
    var astroTag = "Nacht";
    
    for (var i = 0; i < objekt.length-6; i++) {
        // Temporäre Zahl
        var tmp_ergebnis = 0;

        // Hole Uhrzeit aus aktuellem Datenpunkt
        var dp_zeit = getState(datenpunkt+objekt[i]).val;
        
        // Hole Index aktuelle Tageszeit
        var tmp_time_uhr = Date.parse('1970-01-01 '+uhrzeit+':00');
        var tmp_time_dp = Date.parse('1970-01-01 '+dp_zeit+':00');
        
        // Aktuelle Zeit ist kleiner als DP
        if (tmp_time_uhr<tmp_time_dp) {
            tmp_ergebnis = tmp_time_dp-tmp_time_uhr;
            if (tmp_ergebnis<=ergebnis || ergebnis==-1) {
                ergebnis = tmp_ergebnis;
                astro_index = i;
                naechste_element = true;
            }
        // Aktuelle Zeit ist größer als DP
        } else {
            tmp_ergebnis = tmp_time_uhr-tmp_time_dp;
            if (tmp_ergebnis<=ergebnis || ergebnis==-1) {
                ergebnis = tmp_ergebnis;
                astro_index = i;
                naechste_element = false;
            }
        }
        // Datenpunkt ist kleiner als aktuelle Uhrzeit. Update!
        if (dp_zeit<uhrzeit) {
            // Neue Astro-Zeit für den nächsten Tag generieren
            var morgen = new Date();
            morgen.setDate(morgen.getDate() + 1);
            var astro_zeit = zeit_formatieren(getAstroDate(objekt[i], morgen));
            // Datenpunkt und Astro Zeit sind gleich. Kein Update!
            if (dp_zeit==astro_zeit) {
                keine_aktualisierung++;
            } else {
                if (astro_zeit=="Invalid Date") {
                    astro_zeit = "00:00";
                }                
                setState(datenpunkt+objekt[i], astro_zeit);
                aktualisiert++;
            }
        } else {
            // Zeit kommt noch! Kein Update!
            aktuell++;
        }
    }
    // Wenn wahr, ist der Abstand zum nächsten Zeitpunkt kleiner. Also -1 um aktuellen Index zu erhalten.
    if (naechste_element) {
        astro_index--;
    }
    
    // Navigiere zum richtigen Index
    if (astro_index>12) {
        aktuelle_tageszeit = 13;
        kommende_tageszeit = 0;
    } else if (astro_index<0) {
        aktuelle_tageszeit = 0;
        kommende_tageszeit = 1;
    }else {
        aktuelle_tageszeit = astro_index;
        kommende_tageszeit = astro_index+1;
    }

    // Prüfe, ob aktuelle Uhrzeit zwischen Sonnenauf- und untergang liegt
    if (astro_index>2 && astro_index<10) {
        astroTag = "Tag";
    }

    // Update aktuelle Tageszeit Astro (Text)
    setState(datenpunkt+objekt[14],text_formatieren(beschreibung[aktuelle_tageszeit]));
    
    // Update kommende Tageszeit Astro (Text)
    setState(datenpunkt+objekt[15],text_formatieren(beschreibung[kommende_tageszeit]));

    // Update aktuelle Tageszeit lesbar (Text)
    setState(datenpunkt+objekt[16],lesbare_zeiten[aktuelle_tageszeit]);

    // Update kommende Tageszeit lesbar (Text)
    setState(datenpunkt+objekt[17],lesbare_zeiten[kommende_tageszeit]);

    // Update aktuelle AstroZeit
    setState(datenpunkt+objekt[18],objekt[aktuelle_tageszeit]);

    // Setze die Variable "Tag" auf "Tag", wenn Uhrzeit zwischen Sonnenauf- und untergang
    setState(datenpunkt+objekt[19],astroTag);
        
    var ausgabe = "Astro: Gültige Zeiten: [aktueller Tag: "+aktuell+"] | [nächster Tag: " +keine_aktualisierung+"] | [Aktualisiert: "+ aktualisiert+
                "] | Aktuelle Tageszeit: "+lesbare_zeiten[aktuelle_tageszeit]+" | Kommende Tageszeit: "+lesbare_zeiten[kommende_tageszeit];
    log (ausgabe);
}

// Funktion, um die Zeit in HH:MM zu formatieren
function zeit_formatieren(zeit) {
    return zeit.toLocaleTimeString('de-DE',{ hour12: false, hour:'2-digit', minute:'2-digit' });
}

// Funktion, um den Text zu formatieren. "Mittag" statt "6 - Mittag"
function text_formatieren(text) {
    text = text.split("-")[1];
    text = text.substr(1, text.length);
    return text;
}

// Erster Start des Skripts und anlegen der Datenpunkte
function update_astro_zeiten_erster_start() {
    log ("Astro: Erster Start des Skriptes!")
    // Datenpunkte werden erstellt
    datenpunkte_erstellen();

    // erstes Füllen der Datenpunkte um 3 Sek. verzögert
    setTimeout(datenpunkte_fuellen,3000);

    // Das Update der Zeiten ist um 5 Sek. verzögert
    setTimeout(update_astro_zeiten,5000);
}

// Erster Start und Initialisierung
update_astro_zeiten_erster_start();

// Alle 60 Minunten das Hauptskript ausführen
schedule('*/30 * * * *', update_astro_zeiten);

Einbindung in VIS

Um nun die aktuelle Tageszeit in VIS anzeigen zu können, kannst Du einfach ein String Widget auf deine View ziehen und den Datenpunkt verknüpfen.

String Widget
String Widget auf der View platzieren

Folgender Datenpunkt wird dem String zugewiesen:

javascript.0.Astro.tageszeitLesbar
Datenpunkt der Tageszeit
Uhrzeit

ioBroker Skript um zu prüfen, ob die aktuelle Uhrzeit innerhalb eines bestimmten Zeitfensters liegt

Mit ioBroker und JavaScript lässt sich (fast) alles einstellen, umstellen, kontrollieren oder überwachen. Mit diesem Skript kannst Du eine Funktion implementieren, die prüft, ob die aktuelle Uhrzeit im Bereich einer Zeitspanne liegt. Diese arbeitet auch tagübergreifend. So kann eine Startzeit bei 05:00:00 liegen und um 04:30:00 enden. Somit ist klar, das der Endzeitpunkt am nächsten Tag liegt.

Skript in ioBroker anlegen

Dieses Skript legst Du am Besten wieder im global Bereich an, damit es auch von anderen Skripten im common Bereich genutzt werden kann.

function Zeitbereich(startTime,endTime) {
     // Aktuelles Datum abholen
     var currentDate = new Date();
     // Startdatum formatieren   
     var startDate = new Date(currentDate.getTime());
     startDate.setHours(startTime.split(":")[0]);
     startDate.setMinutes(startTime.split(":")[1]);
     startDate.setSeconds(startTime.split(":")[2]);
 
     // Enddatum formatieren
     var endDate = new Date(currentDate.getTime());
     endDate.setHours(endTime.split(":")[0]);
     endDate.setMinutes(endTime.split(":")[1]);
     endDate.setSeconds(endTime.split(":")[2]);
 
     //Setze Zeitbereich zurück
     var valid_time_frame = false
     
     if (endTime > startTime) {
         // Zeitbereich ist im gleichen Tag
         valid_time_frame = (currentDate >= startDate && currentDate <= endDate) ? true : false;
     } else {
         // Zeitbereich endet im nächsten Tag
         valid_time_frame = (currentDate >= endDate && currentDate <= startDate) ? false : true;
     }
     return valid_time_frame;
 }

Andere Skripte können nun die Funktion Zeitbereich(start,ende); nutzen.
Der Funktionsaufruf ist wie folgt:

if (Zeitbereich("05:00:00","04:30:00")) {
     // Zeitbereich zwischen 5 Uhr morgens und 4:30 Uhr des nächsten Morgens
     // Hier kannst Du etwas ausführen lassen, was zu dem Zeitraum passt.
 }
 
 if (Zeitbereich("09:00:00","13:00:00")) {
     // Zeitbereich zwischen 9 Uhr morgens und 13:00 Uhr mittags
     // Hier kannst Du etwas ausführen lassen, was zu dem Zeitraum passt.
 }
 

Dieses Skript lässt sich hervorragend mit meinem Beitrag:
HomeMatic Sprachausgabe mit Alexa, ioBroker und JavaScript verwenden.

Zeitsteuerung

Zeitgesteuerte Schaltungen, Zeitsteuerungen & Intervallschaltungen mit JavaScript in ioBroker

In einem vergangenen Beitrag hast Du bereits die Ereignissteuerungen kennengelernt. Hier geht es nun um die zeitgesteuerten Ereignisse in JavaScript. Zeitgesteuerte Ereignisse sind die, die nicht von einem Gerät, sondern von einem Zeitpunkt oder Zeitintervall ausgelöst werden.

Zeitgesteuerte Schaltung

Damit nun auch, wie eingangs erwähnt, der Zeitpunkt der Auslöser ist kann man natürlich eine Zeitsteuerung in HomeMatic nutzen. Was aber, wenn das Gerät nicht zu HomeMatic gehört oder vielleicht keine eigene Zeitsteuerung hat? Hier lässt sich mit wenig Aufwand eine Zeitsteuerung in JavaScript realisieren.

schedule({hour: 20, minute: 00}, TV_taeglich_an );
  
 function TV_taeglich_an() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", true);
 }

Über den Parameter schedule wurde nun die Zeitsteuerung für hour und minute aktiviert. Hier wird zeitgesteuert das TV täglich um 20 Uhr eingeschaltet.

Zeitgesteuerte Schaltung nur an einem bestimmten Tag

Möchte man nun, dass das Skript nur an einem bestimmten Tag ausgeführt wird, so bedient man sich dem Parameter dayOfWeek. Dieser erwartet eine oder mehrere Zahlen.

schedule({hour: 20, minute: 00, dayOfWeek: 0}, TV_nur_Sonntag_an );
  
 function TV_nur_Sonntag_an() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", true);
 }

In der Programmierung fangen die Zahlen oder Indizes mit 0 an – somit ist auch hier die erste Zahl eine 0 – aber ein Sonntag.

ZahlWochentag
0Sonntag
1Montag
2Dienstag
3Mittwoch
4Donnerstag
5Freitag
6Samstag
Belegung der Wochentage

Zeitgesteuerte Schaltung an bestimmten Tagen

Mit diesem leicht modifizierten Skript, lässt sich die Schaltung auf die Tage 1-5 (Montag bis Freitag) eingrenzen. Dazu wird jeder Tag durch Komma getrennt in eckige Klammern eingegeben.

schedule({hour: 20, minute: 00, dayOfWeek: [1,2,3,4,5]}, TV_nur_Mo_Fr_an );
  
 function TV_nur_Mo_Fr_an() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", true);
 }

Intervallschaltungen

Minütliche Intervallschaltungen

In diesem Skript lassen wir ein Skript jede Minute ausführen. Dazu benutzen wir den Parameter second und geben ihm den Wert 00.

schedule({second: [00]}, Jede_Minute );
  
 function Jede_Minute() {
   log("Skript wird jede Minute ausgeführt!");
 }

Zeitsteuerung alle 30 Minuten

Hier bedienen wir uns des Parameters minute und geben ihm die Werte 00 und 30. Dies wäre dann jede halbe Stunde. 15:00 und 15:30.

schedule({minute: [00,30]}, Alle_30_Minuten );
  
 function Alle_30_Minuten() {
   log("Skript wird alle 30 Minuten ausgeführt!");
 }

Zeisteuerung jede Stunde

Um ein Skript jede Stunde ausführen zu lassen, kann man dies auch wieder über den minute Parameter einrichten. Man gibt ihm den Wert 00.

schedule({minute: [00]}, Jede_Stunde );
  
 function Jede_Stunde() {
   log("Skript wird jede Stunde ausgeführt!");
 }

Schaltung mit Sonnenaufgang und -untergang

Normale Schaltung

Es lassen sich mit JavaScript auch Schaltungen zu astronomischen Ereignissen ausführen. Diese Schaltung schaltet täglich das TV zum astronomischen Sonnenaufgang ein.

schedule({astro: "sunrise"}, TV_bei_Sonnenaufgang_ein );
  
 function TV_bei_Sonnenaufgang_ein() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", true);
 }

… und dieses schaltet das TV zum astronomischen Sonnenuntergang wieder aus.

schedule({astro: "sunset"}, TV_bei_Sonnenuntergang_aus );
  
 function TV_bei_Sonnenuntergang_aus() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", false);
 }

Für astro stehen folgende Werte zur Verfügung:

WertBeschreibung
sunriseSonnenaufgang (Oberkante der Sonne erscheint am Horizont)
sunriseEndSonnenaufgang endet (unterer Rand der Sonne berührt den Horizont)
goldenHourEndDie goldene Morgenstunde (weiches Licht, beste Zeit für Fotografie) endet
solarNoonSonnenmittag (Sonne steht am höchsten)
goldenHourDie goldene Abendstunde beginnt
sunsetStartSonnenuntergang beginnt (unterer Sonnenrand berührt den Horizont)
sunsetSonnenuntergang (Sonne verschwindet unter dem Horizont, abendliche zivile Dämmerung beginnt)
duskAbenddämmerung (abendliche nautische Dämmerung beginnt)
nauticalDusknautische Dämmerung (abendliche astronomische Dämmerung beginnt)
nightNacht beginnt (dunkel genug für astronomische Beobachtungen)
nightEndDie Nacht endet (die astronomische Dämmerung am Morgen beginnt)
nauticalDawnnautische Morgendämmerung (morgendliche nautische Dämmerung beginnt)
dawnMorgendämmerung (die nautische Dämmerung am Morgen endet, die zivile Dämmerung am Morgen beginnt)
nadirdunkelster Moment der Nacht, Sonne steht am niedrigsten
Werte der Variable astro

Schaltung mit Verzögerung/vorzeitigem Eintritt bei Sonnenaufgang und -untergang

Wenn der genaue Zeitpunkt für Sonnenaufgang oder -untergang zu früh oder zu spät eintritt, so lässt sich mit dieser Modifikation eine Verzögerung oder ein vorzeitiger Eintritt der Ausführung einrichten.

Dieses Skript schaltet das TV 10 Minuten nach dem Sonnenaufgang ein.

schedule({astro: "sunrise", shift: 10}, TV_bei_Sonnenaufgang_ein );
  
 function TV_bei_Sonnenaufgang_ein() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", true);
 }

… und dieses schaltet das TV 10 Minuten vor dem Sonnenuntergang aus.

schedule({astro: "sunset", shift: -10}, TV_bei_Sonnenaufgang_ein );
  
 function TV_bei_Sonnenaufgang_ein() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", false);
 }

Schaltung mit Verzögerung an einem bestimmten Tag

Schaltungen mit der Astrofunktion lassen sich auch nur an bestimmten Wochentagen ausführen. Hier wird das Licht 10 Minuten nach Sonnenaufgang an einem Samstag eingeschaltet.

schedule({astro: "sunrise", shift: 10, dayOfWeek:6}, TV_bei_Sonnenaufgang_ein_nur_Samstag );
  
 function TV_bei_Sonnenaufgang_ein_nur_Samstag() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", true);
 }

Schaltung mit Verzögerung an bestimmten Tagen

Schaltungen mit der Astrofunktion lassen sich auch nur an mehreren Wochentagen ausführen. Hier wird das Licht an Samstag und Sonntag 10 Minuten nach dem Sonnenaufgang eingeschaltet.

schedule({astro: "sunrise", shift: 10, dayOfWeek:[0,6]}, TV_bei_Sonnenaufgang_ein_nur_Wochenende );
  
 function TV_bei_Sonnenaufgang_ein_nur_Wochenende() {
   setState("hm-rpc.2.00085A499BF6D2.4.STATE", true);
 }
Events

ioBroker Ereignisse (Events) mit JavaScript überwachen

Eine Haus-Automatisierung ist im groben Prinzip eine Verkettung von “wenn -> dann” Abfolgen. Z.B. Wenn Schalter betätigt, dann Licht an; Wenn 20 Uhr abends jeden Tag, dann TV an. Viele dieser Funktionen lassen sich mit direkten Verknüpfungen innerhalb einer Gerätefamilie einrichten. Andere hingegen lassen sich über einen kleinen Umweg auch geräteübergreifend realisieren.

HomeMatic Aktor mit HomeMatic Schalter/Taster schalten

Eine schöne Art und Weise zum Schalten ist die direkte Verknüpfung zwischen einem HomeMatic Schalter und einem Aktor. Dieser lässt sich in der HomeMatic konfigurieren.

Direkte Verknüpfung in HomeMatic
Direkte Verknüpfung in HomeMatic

ioBroker Gerät/Datenpunkt mit HomeMatic Schalter/Taster schalten

Möchtest Du nun aber ein anderes Gerät mit einem HomeMatic Schalter/Taster schalten, so ist dies mit der HomeMatic nicht so einfach möglich. Klar, für manche Geräte gibt es Workarounds o.ä. Eine elegantere Lösung stellt hier das JavaScript in ioBroker dar, denn dieses kann plattformunabhängig reagieren. Als Beispiel möchte ich jetzt mit einem HomeMatic Schalter meinen Onkyo Receiver (über Onkyo Adapter verbunden) mit dem Taster einschalten.

on({id: 'hm-rpc.0.OEQ0613813.1.PRESS_SHORT', change: 'any'}, function(obj) {
    setState("onkyo.0.Zone1.Power", true);
 });

Über den Parameter on in der ersten Zeile lassen sich Datenpunkte “abonnieren”. Mit dem nächsten Parameter change lässt sich JavaScript anweisen, wie es auf Änderungen reagieren soll. Dazu ist in der nächsten Tabelle ersichtlich, welche Werte verwendet werden können.

WertBeschreibung
anyTrigger wird immer ausgeführt
eqDer neue Wert muss gleich dem Alten sein
geNeuer Wert muss größer oder gleich groß sein
gtNeuer Wert muss größer als der alte Wert sein
leNeuer Wert muss kleiner oder gleich groß sein
ltNeuer Wert muss kleiner als der alte sein
neDer neue Wert muss nicht gleich dem Alten sein (Standard)
Übersicht der change Parameter

Sollten Dich zeitgesteuerte Schaltungen auch interessieren, so findest du hier meinem Beitrag zu dem Thema.