Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. [Skript] Verständnisfrage Trigger

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    [Skript] Verständnisfrage Trigger

    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      Pittini Developer last edited by

      Hi allerseits, ganz kurze Frage:

      on(id1[1][5], function (dp) { //Bei Änderung AstroChoice
      MyTimer[1][5] = getState(id1[1][5]).val; //Nach Änderung neuen Wert einlesen
      KillTimer(1);
      SetTimer(1);
      if (logging) log("AstroChoice geändert");
      });

      funktioniert einwandfrei. Ersetz ich jetzt aber die 1er mit ner Variable wie geplant, krieg ich beim getState nen Fehler. Warum?

      Also SO gehts nicht:
      var x=1;
      on(id1[x][5], function (dp) { //Bei Änderung AstroChoice
      MyTimer[x][5] = getState(id1[x][5]).val; //Nach Änderung neuen Wert einlesen
      KillTimer(x);
      SetTimer(x);
      if (logging) log("AstroChoice geändert");
      });

      Wo is mein (Denk-)Fehler?

      thewhobox 1 Reply Last reply Reply Quote 0
      • thewhobox
        thewhobox @Pittini last edited by

        @Pittini Hallo erstmal. Setz deinen Code doch bitte in den entsprechenden Code Tag, damit man ihn besser lesen kann. (Links vom Link, der Kette).

        //Sieht dann so aus.
        on(id1[x][5], function (dp) {
           [...]
        });
        

        Was ist denn der Fehler?
        Log mal id1[x][5] vor dem getState.

        Ändert sich x im Laufe des scripts?

        1 Reply Last reply Reply Quote 0
        • AlCalzone
          AlCalzone Developer last edited by

          Ich vermute, du bist gerade auf folgendes Problem (analog) gestoßen:
          https://wsvincent.com/javascript-closure-settimeout-for-loop/

          In vielen Fällen lässt sich das durch let anstatt var und/oder Arrow-Funktionen () => { ... } anstatt function() { ... } lösen. Dazu müssten wir aber vollständigen Code sehen 😉

          1 Reply Last reply Reply Quote 0
          • P
            Pittini Developer last edited by

            Ok, zum ganzen Code, erstmal kurz ne Erklärung was der eigentlich soll bzw. was mein Plan ist.
            Ich hab keinen flexiblen Timer gefunden den ich beliebig Anpassen und einsetzen kann, also dacht ich selbermachen und wenns was taugt freut sich sicher auch die Community dann. Zum Code gibts auch ein passendes vis

            2019-05-21 17_48_10-vis.png

            Für einen An,Aus Timer braucht man 2 dieser Blöcke, es gehen aber auch mehr. Im Dropdown gibts auch die Option "Zeit", daurch ändert sich das vis zu:

            2019-05-21 17_54_46-vis.png

            Im script leg ich die Datenpunkte einmalig an und Kommentier den Teil des scripts dann aus. Das isn Workaround weil mir sonst die Datenpunkt immer mit den defaults überschrieben werden. Egal, dasn anderes Problem, der Workaround funktioniert ja.
            Die ganze Struktur ist als mehrdimensionales Array angelegt, die erste Ebene zählt einfach die Timer durch, auf der 2ten liegen dann quasi die Eigenschaften meines spezifischen Timers.
            So kann ich beliebig viele Timer anlegen und Verwalten da alles durch Loops erzeugt wird.
            Tja und nu wollte ich ja eigentlich auch die Trigger loopen weil sich da ja nix ändert. Genau da hustet mir js aber was.
            Hier der ganze Code:

            //Wichtige Einstellungen
            const AnzahlTimer = 2; //Wieviele Timer anlegen? Der erste ist 1, nicht 0!
            const id0 = "broadlink2.0.States.Outlet_2"; //Zu schaltendes Device 
            const logging = true; //Logmeldungen an/aus
            const praefix = "javascript.1.Meine_Geraete.Outlet_2.Zeitschaltung."; //Produktiv auf 0, zum testen auf 1
            
            var Wochentage = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]; //Array für createStateschleife zum anlegen der Wochentage
            var Astrotrigger = ["dawn", "sunrise", "dusk", "goldenHour", "dusk", "sunset"]; //Array für Astro 
            var TimerState = ["Ein", "Aus"];
            //if (logging) { log(Astrotrigger.length.toString()) };
            var x; //Anzahl der Timer
            var y; //Zähler für Wochentage
            var z; //Zähler
            
            /*
            for (x = 1; x < AnzahlTimer + 1; x++) {
                //Datenpunkte anlegen 
                createState(praefix + x + ".Aktiv", false, { read: true, write: true, name: "Timer aktiv", type: "boolean", role: "switch", def: false }); //Legt fest ob der Timer aktiv ist
                createState(praefix + x + ".Rolle", true, { read: true, write: true, name: "Rolle", type: "boolean", role: "switch", def: true }); //Legt fest ob der Timer für An oder Aus zuständig ist
                createState(praefix + x + ".TimerTimestamp", "00:00:00", { read: true, write: true, name: "Zeitstempel für schaltzeit", type: "string" });
                createState(praefix + x + ".TimerAstroTimestamp", "00:00:00", { read: true, write: true, name: "Zeitstempel für Astroschaltzeit", type: "string" });
                createState(praefix + x + ".TimerAstroShift", 0, { read: true, write: true, name: "Zeitverschiebung für Astroschaltzeit", type: "number" });
                for (y = 0; y < 7; y++) { //Einträge für jeden Wochentag anlegen
                    createState(praefix + x + ".Timer" + Wochentage[y], true, { read: true, write: true, name: Wochentage[y], type: "boolean", role: "switch", def: true });
                }
                createState(praefix + x + ".TimerChoice", "Zeit",{ read: true, write: true, name: "Funktionswahl für Timer/Astro", type: "string", def: "Zeit" }); //Gewählte Funktion, Timer oder Astro
            };
            //****************************
            */
            //Datenpunkte Id"s zuweisen
            //x = 0; //Anzahl der Timer
            //z = 0; //Schleifenvariable für Wochentage
            var id1 = [];
            for (x = 1; x < AnzahlTimer + 1; x++) {
                y = 0;
                id1[x] = [];
                id1[x][y] = (praefix + x + ".Aktiv"); y = y + 1;
                id1[x][y] = (praefix + x + ".Rolle"); y = y + 1;
                id1[x][y] = praefix + x + ".TimerTimestamp"; y = y + 1;
                id1[x][y] = praefix + x + ".TimerAstroTimestamp"; y = y + 1;
                id1[x][y] = praefix + x + ".TimerAstroShift"; y = y + 1;
                id1[x][y] = praefix + x + ".TimerChoice"; y = y + 1;
                for (z = 0; z < Wochentage.length; z++) {
                    id1[x][y] = praefix + x + ".Timer" + Wochentage[z]; y = y + 1;
                };
            };
            
            if (logging) {
                for (x = 1; x < AnzahlTimer + 1; x++) {
                    for (z = 0; z < id1[x].length; z++) {
                        if (logging) log(id1[x][z] + " z=" + z + " x=" + x);
            
                    };
                };
            };
            
            // TimerVariablenArray anlegen für schedules
            var TimerAction = [];
            for (x = 1; x < AnzahlTimer + 1; x++) {
                TimerAction[x] = null;
            };
            
            //Alle Daten in MyTimer Array einlesen
            var MyTimer = [];
            for (x = 1; x < AnzahlTimer + 1; x++) {
                MyTimer[x] = [];
                for (y = 0; y < id1[x].length; y++) {
                    //log("x=" + x + "  y=" + y);
                    MyTimer[x][y] = getState(id1[x][y]).val;
                    //log(MyTimer[x][y]);
                };
            };
            
            function MakeCronString(whichone) { //String nach Cronsyntax zusammenbauen für Schedule
                var DaysSubString = "";
                for (x = 0; x < 7; x++) {
                    if (MyTimer[whichone][x + 6] == true) { //Beginnend mit dem 6ten Eintrag (TimerSonntag) die 7 Wochentage durchzählen und Werte anhängen
                        DaysSubString = DaysSubString + x + ",";
                    };
                };
                DaysSubString = DaysSubString.substr(0, DaysSubString.length - 1);//Komma am Ende entfernen
                log(DaysSubString);
            
                var tempString = "";
                if (MyTimer[whichone][5] == "Zeit") { //Wenn Zeit gewählt
                    tempString = SplitTime(MyTimer[whichone][2])[1] + " " + SplitTime(MyTimer[whichone][2])[0] + " * * " + DaysSubString;
                    log("CronString für Timer ausgelöst " + tempString);
                }
                else if (MyTimer[whichone][5] != "Zeit") { //Wenn Astro gewählt
                    var tempTime = calcTime(whichone);
                    tempString = SplitTime(tempTime)[1] + " " + SplitTime(tempTime)[0] + " * * " + DaysSubString;
                    // tempString = SplitTime(MyTimer[whichone][3])[1] + " " + SplitTime(MyTimer[whichone][3])[0] + " * * " + DaysSubString;
                    log("Cronstring für Astro ausgelöst " + tempString);
                };
                return tempString;
            };
            
            //spezifischen Timer setzen
            function SetTimer(whichone) {
                if (MyTimer[whichone][0] == true) { //Ist der Timer aktiv?
                    log("Timer " + whichone + " Set")
                    TimerAction[whichone] = schedule(MakeCronString(whichone), function () {
                        DoAction(whichone);
                    });
                };
            
            };
            
            
            //Alle Timer setzen
            function SetAllTimer() {
                for (x = 1; x < AnzahlTimer + 1; x++) {
                    SetTimer(x);
                }
            };
            
            //spezifischen Timer löschen
            function KillTimer(whichone) {
                clearSchedule(TimerAction[whichone]);
                log("Timer " + whichone + " killed");
            }
            
            //Shift mit Astrotime verrechnen
            function calcTime(whichone) {
                var Shift = parseInt(MyTimer[whichone][4]); //Wert für Shift
                var AstroTime = getDateObject(MyTimer[whichone][3]); //Astrotime einlesen
                //log(AstroTime);
                AstroTime.setMinutes(AstroTime.getMinutes() + Shift);//zammrechna
                log("Astrozeit mit Shift verrechnet. Neue Zeit=" + AstroTime.toLocaleTimeString());
                return AstroTime.toLocaleTimeString();
            };
            
            /*/Astro oder Zeit Gateway
            function AstroOrTime(whichone) {
                if (MyTimer[whichone][5] == "Zeit") {
                    log("Zeit gewählt " + MyTimer[whichone][2]);
                }
                else if (MyTimer[whichone][5] != "Zeit") {
                    GetChoosenAstroTime(whichone);
                    log("Astro gewählt, Variante " + MyTimer[whichone][5]);
                };
            };*/
            
            function GetChoosenAstroTime(whichone) { //Zeit für gewählte Astrozeit eintragen
                var Shift = MyTimer[whichone][4]; //Wert für Shift
                var AstroTime = MyTimer[whichone][3]; //Wert für Astrotime
                var AstroChoice = MyTimer[whichone][5].trim(); //Wert für Astroereignis
                AstroTime = getAstroDate(AstroChoice).toLocaleTimeString();
                log(Shift + AstroTime + AstroChoice);
                setState(id1[whichone][3], AstroTime);
            };
            
            function DoAction(whichone) {
                if (MyTimer[whichone][0] == true) { //Wenn Timer aktiv
                    if (MyTimer[whichone][1] == true) { // Wenns ein Anschalter ist
                        setState(id0, true);
                        log("Timer " + whichone + " hat angeschaltet");
                    }
                    else if (MyTimer[whichone][1] == false) { //Wenns ein Ausschalter ist
                        setState(id0, false);
                        log("Timer " + whichone + " hat ausgeschaltet");
                    };
                };
            };
            
            function main(){
                SetAllTimer();
            };
            
            main();
            
            //Trigger für Timer1
            on(id1[1][5], function (dp) { //Bei Änderung AstroChoice
                MyTimer[1][5] = getState(id1[1][5]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
                if (logging) log("AstroChoice geändert");
            });
            
            on(id1[1][1], function (dp) { //Bei Änderung AstroChoice
                MyTimer[1][1] = getState(id1[1][1]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
                if (logging) log("Rolle geändert");
            });
            
            on(id1[1][4], function (dp) { //Bei Änderung Shift
                MyTimer[1][4] = getState(id1[1][4]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
                if (logging) log("Shift geändert");
            });
            
            on(id1[1][2], function (dp) { //Bei Änderung Zeit (TimerTimestamp)
            
                setTimeout(function () { //1sek Timeout um prellen zu vermeiden
                    MyTimer[1][2] = getState(id1[1][2]).val; //Nach Änderung neuen Wert einlesen
                    KillTimer(1);
                    SetTimer(1);
                    if (logging) log("TimerTimestamp Zeit geändert auf " + MyTimer[1][2]);
                }, 1000);
            
            });
            
            on(id1[1][0], function (dp) { //Bei Änderung Timer Aktiv
                MyTimer[1][0] = getState(id1[1][0]).val; //Nach Änderung neuen Wert einlesen
                if (logging) log("TimerActive geändert auf " + MyTimer[1][0]);
                KillTimer(1);
                //SetTimer(1);
            
            });
            
            on(id1[1][6], function (dp) { //Bei Änderung Wochentage
                MyTimer[1][6] = getState(id1[1][6]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
            
                if (logging) log("TimerTag " + Wochentage[0] + " geändert auf " + MyTimer[1][6]);
            });
            on(id1[1][7], function (dp) { //Bei Änderung Wochentage
                MyTimer[1][7] = getState(id1[1][7]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
            
                if (logging) log("TimerTag " + Wochentage[1] + " geändert auf " + MyTimer[1][7]);
            });
            on(id1[1][8], function (dp) { //Bei Änderung Wochentage
                MyTimer[1][8] = getState(id1[1][8]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
            
                if (logging) log("TimerTag " + Wochentage[2] + " geändert auf " + MyTimer[1][8]);
            });
            on(id1[1][9], function (dp) { //Bei Änderung Wochentage
                MyTimer[1][9] = getState(id1[1][9]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
            
                if (logging) log("TimerTag " + Wochentage[3] + " geändert auf " + MyTimer[1][9]);
            });
            on(id1[1][10], function (dp) { //Bei Änderung Wochentage
                MyTimer[1][10] = getState(id1[1][10]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
            
                if (logging) log("TimerTag " + Wochentage[4] + " geändert auf " + MyTimer[1][10]);
            });
            on(id1[1][11], function (dp) { //Bei Änderung Wochentage
                MyTimer[1][11] = getState(id1[1][6]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
            
                if (logging) log("TimerTag " + Wochentage[5] + " geändert auf " + MyTimer[1][11]);
            });
            on(id1[1][12], function (dp) { //Bei Änderung Wochentage
                MyTimer[1][12] = getState(id1[1][12]).val; //Nach Änderung neuen Wert einlesen
                KillTimer(1);
                SetTimer(1);
            
                if (logging) log("TimerTag " + Wochentage[6] + " geändert auf " + MyTimer[1][12]);
            });
            
            
            //***************Zeit in Stunden und Minuten teilen für späteren Cronstring
            function SplitTime(Time) {
                var timesplit = Time.split(":", 2);
                //h = timesplit[0]  / m = timesplit[1];
                return timesplit;
            };
            
            // Ab hier Tests, einfach ignorieren
            
            //if (logging) { log(SplitTime("12:05") + h + m) };
            //***************
            

            Das ist mein Zwischenstand der soweit funktioniert, is aber noch nicht ganz fertig und nur minimal getestet.
            Ich verwende btw. kein astro schedule, sondern mache alles mitm normalen schedule.

            So das ganze ist jetzt für einen Timer, meist brauch ich aber mind. zwei davon (Ein/Aus) also war der Plan unten im Teil der mitt Trigger Timer1 kommentiert ist, die ganzen on auch zu loopen was dann so aussähe:

            //Trigger für Timer1
            for (x = 1; x < AnzahlTimer+1; x++) {
                on(id1[x][5], function (dp) { //Bei Änderung AstroChoice
                    MyTimer[x][5] = getState(id1[x][5]).val; //Nach Änderung neuen Wert einlesen
                    KillTimer(x);
                    SetTimer(x);
                    if (logging) log("AstroChoice geändert");
                });
            };
            
            

            Starten kann ich das Script jetzt, aber sobald der Trigger auslöst, also das getState ausgeführt wird kommt:

            18:16:36.719 error javascript.0 at Object.<anonymous> (script.js.Meine_Geräte.Steckdose2.Timer:175:40)

            Tja und nu steh ich da und verstehs nicht. Was nix heißen muss, ich bin n Dinosaurier und ganz sicher nicht uptodate.
            Wäre nett wenn noch mal wer drüberschaut.

            AlCalzone 1 Reply Last reply Reply Quote 0
            • AlCalzone
              AlCalzone Developer @Pittini last edited by

              @Pittini sagte in [Skript] Verständnisfrage Trigger:

              Tja und nu steh ich da und verstehs nicht. Was nix heißen muss, ich bin n Dinosaurier und ganz sicher nicht uptodat

              Ändere

              for (x = 1; x < AnzahlTimer+1; x++)
              

              zu

              for (let x = 1; x < AnzahlTimer+1; x++)
              

              Ohne let (also mit var) ist der Wert von x nicht an den Schleifendurchlauf gebunden. D.h. zu dem Zeitpunkt, zu dem der Trigger aufgerufen wird, hat x den Wert AnzahlTimer+1, welcher für alle Trigger-Callbacks genutzt wird.
              Mit let hat x den Wert, der dem jeweiligen Schleifendurchlauf entspricht.

              P 1 Reply Last reply Reply Quote 0
              • P
                Pittini Developer @AlCalzone last edited by

                @AlCalzone Super, vielen Dank, zumindest kommt so schon mal kein Fehler mehr, wenngleich ichs nicht wirklich versteh, weil ja in Zeile 11 immer noch das Var x steht. Aber ich kann jetzt auf jeden Fall mal weitermachen.
                Weist Du evtl auch noch warum meine createStates immer die Werte mit den defaults überschreiben? Geplant war ein anlegen nur wenn nicht vorhanden. Was ich jetzt mit auskommentieren mach, aber elegant ist das nicht mal für meine Verhältnisse.
                Ach ja und weist kennst Du evtl das Phänomen das sich die Logeinträge vervielfachen immer so nach ca. 15 Stunden wirds einer mehr. Sieht dann z.B. so aus

                2019-05-21 19_06_02-javascript - ioBroker.png

                Das is übrigens vom Script unabhängig, is bei jedem. Nach nem Neustart des PCs is alles wieder normal, nach ca. 15 Stunden isses dann doppelt, dann dreifach usw.. Ich hab das mal als Bug abgehakt, aber vieleicht weißt Du ja näheres.

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

                Support us

                ioBroker
                Community Adapters
                Donate

                891
                Online

                31.8k
                Users

                80.0k
                Topics

                1.3m
                Posts

                3
                6
                405
                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