Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. Time Of Day - Design Pattern

    NEWS

    • 15. 05. Wartungsarbeiten am ioBroker Forum

    • Monatsrückblick - April 2025

    • Minor js-controller 7.0.7 Update in latest repo

    Time Of Day - Design Pattern

    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      Tirador last edited by Tirador

      Hallo,

      nach Suche im Forum habe ich leider kein "Time Of Day"-Pattern gefunden und daher selbst ein kleines Skript geschrieben.

      Worum geht es:

      Abbildung einer Zeitschaltuhr über Zustände der aktuellen Tageszeit.
      Dies Zustände sind beispielweise: Morgen, Nachmittag, Abend, Bettzeit etc.
      Im Prinzip wird der Tag in mehrere Zeitabschnitte eingeteilt und diese in einem Datenpunkt vorgehalten.

      Beispiel:

      // Zustand 	          Start 	                
      //------------------------------------------
      // MORNING 	          05:30 	                
      // DAY 	                  Sunrise 	            
      // HIGHNOON               Solarnoon - 30 minutes   
      // AFTERNOON 	          Solarnoon + 30 minutes 	
      // LATEAFTERNOON          Sunset - 60 minutes
      // EVENING 	          Sunset -5 minutes       
      // NIGHT 	          23:00 	                
      // BED                    00:30     
      

      Bezogen auf das Beispiel nimmt der Datenpunkt den Zustand jeweils mit Eintritt des Start-Ereignisses an.
      D.h. der Zustand "MORNING" startet um 5:30 Uhr und gilt bis zum nächsten Zustandswechsel durch den Zustand "DAY" mit "Sunrise" (Sonnenaufgang).

      Mit Ausführung des Skripts wird ein Datenpunkt "javascript.0.TimeOfDay.timeOfDay.current" erzeugt, der die aktuelle Tageszeit wiederspiegelt:

      2020-02-23 11_30_37-objects - ioBroker.png

      Beispiel: Praktische Anwendung der Lösung:

      Ich nutze das Skript momentan, um die Lampen im Haus automatisiert ein- und auszuschalten.

      2020-02-23 11_32_22-javascript - ioBroker.png

      Jeden Morgen um 5:30 Uhr (MORNING) und 5 Minuten vor Sonnenuntergang (EVENING) werden bestimmte Lampen eingeschaltet. Mit Sonnenaufgang (DAY) und Beginn der Bettzeit (BED) werden die Lampen im gesamten Haus ausgeschaltet. Zusätzlich versende ich noch ein Telegram (zur Kontrolle).

      Beispiel-Blockly:

      <xml xmlns="http://www.w3.org/1999/xhtml">
       <block type="on_ext" id=":=MTl41KBycQ+;j/4`X_" x="-512" y="13">
         <mutation items="1"></mutation>
         <field name="CONDITION">ne</field>
         <field name="ACK_CONDITION"></field>
         <value name="OID0">
           <shadow type="field_oid" id="$PIzJ)HcJ+xW^^UEG!Up">
             <field name="oid">javascript.0.TimeOfDay.timeOfDay.current</field>
           </shadow>
         </value>
         <statement name="STATEMENT">
           <block type="controls_if" id="%-#j95VvTM-,$u6Mz+MR">
             <mutation elseif="1"></mutation>
             <value name="IF0">
               <block type="logic_operation" id="n9wS[qgYJ)B_e8r8?YJ?">
                 <field name="OP">OR</field>
                 <value name="A">
                   <block type="logic_compare" id="KR$c#/d`-MBsc!,@41r-">
                     <field name="OP">EQ</field>
                     <value name="A">
                       <block type="get_value" id="8o)EJuP;tmkRpzWOM8qO">
                         <field name="ATTR">val</field>
                         <field name="OID">javascript.0.TimeOfDay.timeOfDay.current</field>
                       </block>
                     </value>
                     <value name="B">
                       <block type="text" id="wiU7-[.r;FjKA[,L}f6d">
                         <field name="TEXT">EVENING</field>
                       </block>
                     </value>
                   </block>
                 </value>
                 <value name="B">
                   <block type="logic_compare" id="9O9n1tsFKlbi#z3[g,w6">
                     <field name="OP">EQ</field>
                     <value name="A">
                       <block type="get_value" id="y@M0[ZxUMj1SrzqS{9}:">
                         <field name="ATTR">val</field>
                         <field name="OID">javascript.0.TimeOfDay.timeOfDay.current</field>
                       </block>
                     </value>
                     <value name="B">
                       <block type="text" id="3~GJa11^N8F.TJk33JWj">
                         <field name="TEXT">MORNING</field>
                       </block>
                     </value>
                   </block>
                 </value>
               </block>
             </value>
             <statement name="DO0">
               <block type="control" id="6{WrpN%,Tcgb1FK%|ZRS">
                 <mutation delay_input="false"></mutation>
                 <field name="OID">deconz.0.Groups.8.on</field>
                 <field name="WITH_DELAY">FALSE</field>
                 <value name="VALUE">
                   <block type="logic_boolean" id="U3v*bCW~qTYEEPnP9mHq">
                     <field name="BOOL">TRUE</field>
                   </block>
                 </value>
                 <next>
                   <block type="telegram" id="gr#r0JyS*/3mA~htTJ+*">
                     <field name="INSTANCE"></field>
                     <field name="LOG"></field>
                     <field name="SILENT">FALSE</field>
                     <field name="PARSEMODE">default</field>
                     <value name="MESSAGE">
                       <shadow type="text" id="Q:Y1+kLP1aowN.$CUe{G">
                         <field name="TEXT">Abendlicht eingeschaltet!</field>
                       </shadow>
                     </value>
                   </block>
                 </next>
               </block>
             </statement>
             <value name="IF1">
               <block type="logic_operation" id="wz0][pQ5[{2_yS9{rG;Q">
                 <field name="OP">OR</field>
                 <value name="A">
                   <block type="logic_compare" id="B^LcDK@LwSt/bg~,F{=P">
                     <field name="OP">EQ</field>
                     <value name="A">
                       <block type="get_value" id="r6F~NlD.3Wj@ea;wj.5_">
                         <field name="ATTR">val</field>
                         <field name="OID">javascript.0.TimeOfDay.timeOfDay.current</field>
                       </block>
                     </value>
                     <value name="B">
                       <block type="text" id="TU2O.76[SJ+H$!bNb1b!">
                         <field name="TEXT">DAY</field>
                       </block>
                     </value>
                   </block>
                 </value>
                 <value name="B">
                   <block type="logic_compare" id="m?A%zTkx;f^PgTl@exL@">
                     <field name="OP">EQ</field>
                     <value name="A">
                       <block type="get_value" id="4HvOP7dGHdG^J[Grk749">
                         <field name="ATTR">val</field>
                         <field name="OID">javascript.0.TimeOfDay.timeOfDay.current</field>
                       </block>
                     </value>
                     <value name="B">
                       <block type="text" id="[4FUsfXLqE:LWggR0iw_">
                         <field name="TEXT">BED</field>
                       </block>
                     </value>
                   </block>
                 </value>
               </block>
             </value>
             <statement name="DO1">
               <block type="control" id="tD_70D[Bc2|MPyH~h]L/">
                 <mutation delay_input="false"></mutation>
                 <field name="OID">deconz.0.Groups.9.on</field>
                 <field name="WITH_DELAY">FALSE</field>
                 <value name="VALUE">
                   <block type="logic_boolean" id="e)3lrl#l30Z)|i0Lmu8T">
                     <field name="BOOL">FALSE</field>
                   </block>
                 </value>
                 <next>
                   <block type="telegram" id="[yu6jH3e]R57]5x8wDZK">
                     <field name="INSTANCE"></field>
                     <field name="LOG"></field>
                     <field name="SILENT">FALSE</field>
                     <field name="PARSEMODE">default</field>
                     <value name="MESSAGE">
                       <shadow type="text" id="_]MdGpslFX_)_cuH+^YA">
                         <field name="TEXT">Alle Lichter ausgeschaltet!</field>
                       </shadow>
                     </value>
                   </block>
                 </next>
               </block>
             </statement>
           </block>
         </statement>
       </block>
      </xml>
      

      Genauso wie die Lampen gesteuert werden können sind natürlich unendlich weitere Kombinationslogiken möglich.

      Vor/Nachteile der Lösung:

      Sehr einfache Lösung einer "Zeitschaltuhr" ohne komplexen Nebenlogiken.
      Zentralisierung der Logik der Zeitschaltuhr in einem Skript.
      In allen anderen Skripten / Logiken kann man auf den Datenpunkt zugreifen und einfach den Zustand der aktuellen Tageszeit abfragen. Nachteilig ist, dass es keine Überschneidungen von Zeiten gibt. Ebenso werden nur globale Zeiten vorgegeben.

      Ideen/Co-Autoren

      Die Idee des "Time Of Day"-Pattern habe ich von OpenHab übernommen (siehe Desing Pattern: Time of Day).
      Das Skript mit der Astrologik beruhet auf dem Skript von Pix (siehe Iobroker.net Community Post).

      Installation

      In den Haupteinstellungen von IOBroker sind Breiten- und Längengrad vorzugeben, damit die Astro-Funktion die richtigen Zeiten ermitteln kann (für Sonnenaufgang / Sonnenuntergang etc.).

      Das folgende Skript ist als JavaScript "TimeOfDay" einfügen.
      Die Zeiten bzw. weitere Tageszeitzustände können prinzipiell natürlich selbst nochmal an die eigenen Vorgaben angepasst werden.

      Javascript "TimeOfDay"

      //---------------------------------------------------------------
      // Calculating Time of Day Design Pattern
      //---------------------------------------------------------------
      // Idea by OpenHab: see https://community.openhab.org/t/design-pattern-time-of-day/15407)
      // Script see https://forum.iobroker.net/topic/30457/time-of-day-design-pattern
      //---------------------------------------------------------------
      //
      // State 	        Start 	                
      //------------------------------------------
      // MORNING 	        05:30 	                
      // DAY 	            Sunrise 	            
      // HIGHNOON         Solarnoon - 30 minutes   
      // AFTERNOON 	    Solarnoon + 30 minutes 	
      // LATEAFTERNOON    Sunset - 60 minutes
      // EVENING 	        Sunset -5 minutes       
      // NIGHT 	        23:00 	                
      // BED              00:30                   
      //---------------------------------------------------------------
      
      
      const sec = false; // Sekunden darstellen oder nicht
      
      const fC = false; // forceCreation ein/aus
      
      const pfad = "TimeOfDay"; // Pfad zum Objekt - Objektbaum-Hauptverzeichnis
      
      
      const idTageszeit = "javascript." + instance  + "." + pfad + ".timeOfDay.current";
      
       
      
      createState(idTageszeit, "", fC, {
      
        name: "Tageszeit",
      
        desc: "Name der Tageszeit",
      
        type: "string"
      
      });   
      
      
      function setTimeOfDay(newTimeOfDay) {
      
        setState(idTageszeit, newTimeOfDay);
      
        log("Calculating new TimeOfDay: " + newTimeOfDay);
      
      }
      
      //--------------------------------------------------------
      // MORNING - 
      // Start 05:30 
      //--------------------------------------------------------
      
      schedule({
      
        hour: 5, minute: 30
      
      }, function() {
      
          setTimeOfDay("MORNING"); 
      
      });
      
      //--------------------------------------------------------
      // DAY 
      // Start: Sonnenaufgangende Ende
      //--------------------------------------------------------
      
      schedule({
      
        astro: "sunriseEnd"
      
      }, function() {
      
          setTimeOfDay("DAY"); 
      
      });
      
      //--------------------------------------------------------
      // HIGHNOON
      // Start: -30 Minuten vor Sonnenhöchststand 
      //--------------------------------------------------------
      
      schedule({
      
        astro: "solarNoon",
      
        shift: -30
      
      }, function () {
      
        setTimeOfDay("HIGHNOON");
      
      });
      
      //--------------------------------------------------------
      // AFTERNOON
      // Start : +30 Minuten vor Sonnenhöchststand 
      //--------------------------------------------------------
      schedule({
      
        astro: "solarNoon",
      
        shift: 30
      
      }, function () {
      
        setTimeOfDay("AFTERNOON");
      
      });
      
      //--------------------------------------------------------
      // LATEAFTERNOON
      // Start: -60 Minuten vor Sonnenuntergang
      //--------------------------------------------------------
      schedule({
      
        astro: "sunsetStart",
      
        shift: -60
      
      }, function () {
      
         setTimeOfDay("LATEAFTERNOON"); 
      
      });
      
      //--------------------------------------------------------
      // EVENING 
      // Start: -5 Minuten vor Sonnenuntergang 
      //--------------------------------------------------------
      schedule({
      
        astro: "sunsetStart", 
      
        shift: -5
      
      }, function () { 
      
        setTimeOfDay("EVENING"); 
      
      });
      
      
      //--------------------------------------------------------
      // NIGHT
      // Start: 23:00 Uhr
      //--------------------------------------------------------
      schedule({
      
        hour: 23, minute: 0
      
      }, function () { 
      
        setTimeOfDay("NIGHT"); 
      
      });
      
      //--------------------------------------------------------
      // BED
      // Start: 23:00 Uhr
      //--------------------------------------------------------
      schedule({
      
        hour: 0, minute: 30
      
      }, function () { 
      
        setTimeOfDay("BED"); 
      
      });
      
      
      // *****************************************************************************
      
      // A S T O - T E I L 
      
      /* Objekt Astrotag 
      
       Astrotag liegt zwischen Sonnauf- und untergang, 
      
       Astronacht liegt zwischen Sonnenunter- und aufgang */
      
      const idAstrotag =  "javascript." + instance + "." + pfad + ".Astrotag";
      
      // Objekt für Uhrzeiten der Astrozeiten
      
      const astrotime = {
      
        "elements" : [
      
            // Astrotag beginnt
      
            {
      
                "fname" : "sunrise", // function name
      
                "de" : {
      
                    "name" : "Sonnenaufgang",
      
                    "nxt" : "nächster",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "Sunrise",
      
                    "desc" : "top edge of the sun appears on the horizon"
      
                },
      
                "astroday" : true //during astroday
      
            },
      
            {
      
                "fname" : "sunriseEnd", // function name
      
                "de" : {
      
                    "name" : "Ende Sonnenaufgang",
      
                    "nxt" : "nächstes",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "End of sunrise",
      
                    "desc" : "bottom edge of the sun touches the horizon"
      
                },
      
                "astroday" : true //during astroday
      
            },
      
            {
      
                "fname" : "goldenHourEnd", // function name
      
                "de" : {
      
                    "name" : "Ende der goldenen Stunde am Morgen",
      
                    "nxt" : "nächstes",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "End of golden hour",
      
                    "desc" : "morning golden hour (soft light, best time for photography) ends"
      
                },
      
                "astroday" : true //during astroday
      
            },
      
            {
      
                "fname" : "solarNoon", // function name
      
                "de" : {
      
                    "name" : "Sonnenhöchststand",
      
                    "nxt" : "nächster",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "Solar noon",
      
                    "desc" : "sun is in the highest position"
      
                },
      
                "astroday" : true //during astroday
      
            },
      
            {
      
                "fname" : "goldenHour", // function name
      
                "de" : {
      
                    "name" : "Goldene Stunde (am Abend)",
      
                    "nxt" : "nächste",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "Golden hour",
      
                    "desc" : "evening golden hour starts"
      
                },
      
                "astroday" : true //during astroday
      
            },
      
            {
      
                "fname" : "sunsetStart", // function name
      
                "de" : {
      
                    "name" : "Beginn Sonnenuntergang",
      
                    "nxt" : "nächster",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "Sunset starts",
      
                    "desc" : "bottom edge of the sun touches the horizon"
      
                },
      
                "astroday" : true //during astroday
      
            },
      
            // Astronacht beginnt
      
            {
      
                "fname" : "sunset", // function name
      
                "de" : {
      
                    "name" : "Sonnenuntergang",
      
                    "nxt" : "nächster",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "Sunset",
      
                    "desc" : "sun disappears below the horizon, evening civil twilight starts"
      
                },
      
                "astroday" : false //during astronight
      
            },
      
            {
      
                "fname" : "dusk",
      
                "de" : {
      
                    "name" : "Abenddämmerung",
      
                    "nxt" : "nächste",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "Dusk",
      
                    "desc" : "evening nautical twilight starts"
      
                },
      
                "astroday" : false //during astronight
      
            },
      
            {
      
                "fname" : "nauticalDusk",
      
                "de" : {
      
                    "name" : "nautische Abenddämmerung",
      
                    "nxt" : "nächste",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "Nautical dusk",
      
                    "desc" : "evening astronomical twilight starts"
      
                },
      
                "astroday" : false //during astronight
      
            },
      
            {
      
                "fname" : "nadir",
      
                "de" : {
      
                    "name" : "Nadir",
      
                    "nxt" : "nächster",
      
                    "desc" : "Fußpunkt gegenüber dem Zenit"
      
                },
      
                "en" : {
      
                    "name" : "Nadir",
      
                    "desc" : "darkest moment of the night, sun is in the lowest position"
      
                },
      
                "astroday" : false //during astronight
      
            },
      
            {
      
                "fname" : "nauticalDawn",
      
                "de" : {
      
                    "name" : "nautische Morgendämmerung",
      
                    "nxt" : "nächste",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "Nautical dawn",
      
                    "desc" : "morning nautical twilight starts"
      
                },
      
                "astroday" : false //during astronight
      
            },
      
            {
      
                "fname" : "dawn",
      
                "de" : {
      
                    "name" : "Morgendämmerung",
      
                    "nxt" : "nächste",
      
                    "desc" : ""
      
                },
      
                "en" : {
      
                    "name" : "dawn",
      
                    "desc" : "morning nautical twilight ends, morning civil twilight starts"
      
                },
      
                "astroday" : false //during astronight
      
            }
      
       
      
        ]
      
      };
      
       
      
      function writeAstroTimes(i) {
      
        // führende Nummer zur Sortierung in Admin/Objekte
      
        var nr = (i+1 < 10) ? "0" + (i+1) : (i+1);
      
        // Erstelle Objekt, falls nicht bereits vorhanden
      
        var idAstroObject = "javascript." + instance + "." + pfad + ".Zeiten." + nr + " - " + astrotime.elements[i].fname;
      
        createState(idAstroObject, " ", fC, {
      
            name: astrotime.elements[i].de.nxt + " " + astrotime.elements[i].de.name + " Uhrzeit",
      
            desc: astrotime.elements[i].en.desc,
      
            type: "string"
      
        });
      
       
      
        setTimeout(function() { // kurz warten, damit Objekte ggf. erst angelgt werden können
      
            var astrotag = getState(idAstrotag).val,
      
                temp;
      
            var today = new Date();
      
            var tomorrow = new Date(today.setDate(today.getDate()+1));
      
            var next_event;
      
            if (astrotag) { 
      
                // Wenn Tag (Aufgang vorbei (erst wieder morgen, Untergang kommt noch heute)
      
                next_event = (astrotime.elements[i].astroday) ? tomorrow : today; // prüfen
      
            } else { 
      
                // nach Nacht (Untergang vorbei (erst wieder morgen, Aufgang kommt heute oder morgen)
      
                next_event = (astrotime.elements[i].astroday) ? today : tomorrow; // prüfen
      
            }
      
            var fname = astrotime.elements[i].fname;
      
            temp = getAstroDate(fname, next_event);
      
            setState(idAstroObject, checkSec(temp.toLocaleTimeString('de-DE', { hour12: false })) );
      
        }, 3 * 1000);
      
      }
      
       
      
      // Zeit mit oder ohne Sekunden anzeigen
      
      function checkSec (zeit) {
      
        if (!sec) {
      
            var newString_arr = zeit.split(":");
      
            var newString = newString_arr[0] + ":" + newString_arr[1];
      
            return (newString);
      
        } else return (zeit);
      
      }
      
       
      
      function getAstroday() {
      
        // Astrotag bestimmen (boolean)
      
        createState(idAstrotag, false, fC, {
      
            type: "boolean",
      
            name: "Astrologischer Tag",
      
            desc: "Liegt die aktuelle Zeit zwischen Sonnenauf- und untergang"
      
        }); 
      
        setState(idAstrotag, isAstroDay());
      
      }
      
       
      
      function iterateAstrotimes() {
      
        // Zeiten für jede Astrozeit schreiben
      
        for (var i = 0; i < astrotime.elements.length; i++) {
      
            writeAstroTimes(i);
      
        }
      
      }
      
       
      
      // Astrotag checken
      
      schedule("*/1 * * * *", function () { // jede Minute
      
        getAstroday();
      
        iterateAstrotimes();
      
      });
      
       
      
      iterateAstrotimes();
      
      getAstroday();
      
       
      
      

      Optimierungspotenziale

      Im Datenpunkt erscheint der aktuelle Tageszustand erst mit initialem Wechsel der Zeit (hier könnte man bei initialer Ausführung noch den aktuellen Zustand ermitteln!).

      Prizipiell sind die Astro-Funktionen nicht notwendig für das Skript (ich habe sie hier drin, damit ich selbst weiss welche Zeiten ich für Systemzustände setzen kann).

      Aktuell wird das Skript für die Astro-Funktion minütlich aufgerufen (ich hatte dies aus dem Skript von PIX übernommen). Dies ist gar nicht notwendig, es sollte denke ich ausreichen die Astro-Zeiten einmal am Tag neu zu ermitteln (mit Tageswechsel!).

      ? 1 Reply Last reply Reply Quote 3
      • ?
        A Former User @Tirador last edited by

        @Tirador Vielen Dank für das tolle Skript, dass diverse Zeiten einfach über einen DP verfügbar macht 🙂

        1 Reply Last reply Reply Quote 0
        • First post
          Last post

        Support us

        ioBroker
        Community Adapters
        Donate

        626
        Online

        31.6k
        Users

        79.5k
        Topics

        1.3m
        Posts

        javascript template
        2
        2
        1088
        Loading More Posts
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes
        Reply
        • Reply as topic
        Log in to reply
        Community
        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
        The ioBroker Community 2014-2023
        logo