Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. [gelöst]Skript als Alternative zum Scenenadapter

    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

    [gelöst]Skript als Alternative zum Scenenadapter

    This topic has been deleted. Only users with topic management privileges can see it.
    • paul53
      paul53 @Dominik F. last edited by paul53

      @Dominik-F sagte in Skript als Alternative zum Scenenadapter:

      Hier das Script:

      Du verwendest Arrays, wo keine Arrays benötigt werden. Versuche es mal so:

      //Grundeinstellungen
      const logging = true; // Logs ausgeben
      const praefix = "javascript.0.Szenen."; //Grundpfad für Script DPs - Muß innerhalb javascript.x sein.
       
      const SzeneData = [];
      const SzeneID = [];
       
      //Name der Szenen eingeben
      const SzenenName = "Chillen";
       
      //Hier die IDs eingeben
      SzeneID[0] = "zigbee.0.f0d1b8000010bb79.state";  //Stehlampe
      SzeneID[1] = "zigbee.0.7cb03eaa0a068b8d.state";  //Laterne
       
      //Schleife durch die ID's und Werte
      for (let x = 0; x < SzeneID.length; x++) {
          SzeneData[x] = getState(SzeneID[x]).val;
      };
       
      //Datenpunkte erstellen
      createState(praefix + SzenenName + ".activate", { name: "Szene aktivieren/deaktivieren", role: "button" });
      createState(praefix + SzenenName + ".is_activ", { name: "is acitv?", role: "indicator" });
       
      //Ab hier eigentliches Skript
      function Szene() {
          let Status = true;
          for (let x = 0; x < SzeneData.length; x++) {
              if (!SzeneData[x]) Status = false;
          }
          if (logging) {
              if (Status) log("Szene " + SzenenName + " aktiv");
              else log("Szene " + SzenenName + " inaktiv");
          }
          setState(praefix + SzenenName + ".is_activ", Status, true);
      };
       
      Szene();
      for (let x = 0; x < SzeneID.length; x++) { //Trigger in Schleife erstellen
          on(SzeneID[x], function (dp) { // triggert bei Wertänderung
              SzeneData[x] = dp.state.val;
              Szene();
          });
      }
      
      Dominik F. 1 Reply Last reply Reply Quote 1
      • Dominik F.
        Dominik F. @paul53 last edited by

        @paul53

        Das funktioniert ,vielen Dank. Ich habe gerade erst gelernt Arrays zu verwenden, daher hab ich die wahrscheinlich überall eingebaut 😄

        Könntest du mir vielleicht Zeile 28 und deine Änderungen ab Zeile 39 erklären?
        Das logging stimmt noch nicht so ganz. Ich bekomme das logging im Moment doppelt. hast du da noch eine idee?

        paul53 1 Reply Last reply Reply Quote 0
        • paul53
          paul53 @Dominik F. last edited by paul53

          @Dominik-F sagte:

          Zeile 28

          Auf deutsch: Wenn nicht Element x im Array, dann Status = false (ein Element ist nicht true, also false)

          @Dominik-F sagte in Skript als Alternative zum Scenenadapter:

          Änderungen ab Zeile 39 erklären?

          • Einem Trigger (on) muss die ID übergeben werden. Wenn nur die ID als String übergeben wird, wird nur bei Wertänderung getriggert.
          • Der Wert des Trigger-Datenpunktes wird in die passende Position des Daten-Arrays geschrieben und anschließend wird der Inhalt des Daten-Arrays durch Aufruf der Funktion Szene() ausgewertet.

          @Dominik-F sagte in Skript als Alternative zum Scenenadapter:

          Ich bekomme das logging im Moment doppelt. hast du da noch eine idee?

          ? Habe mal die geschweifte Klammern gegen Semikolon ausgetauscht.

          Dominik F. 1 Reply Last reply Reply Quote 1
          • Dominik F.
            Dominik F. @paul53 last edited by

            @paul53

            Vielen Dank für deine Erklärung, wieder was dazu gelernt 🙂

            Das Logging ist immer noch nicht so wie es sein soll. Sobald sich einer der Werte ändert, wird das logging ausgelöst. Mache ich nur einen der beiden Datenpunkte auf true, dann wird szene inaktiv geloggt. Das überschwemmt ja total den log. Es reicht ja, wenn das log ausgelöst wird, wenn der Datenpunkt is_active sich ändert.

            paul53 1 Reply Last reply Reply Quote 0
            • paul53
              paul53 @Dominik F. last edited by

              @Dominik-F sagte:

              Es reicht ja, wenn das log ausgelöst wird, wenn der Datenpunkt is_active sich ändert.

              Dann erweitere Zeile 30.

                  if (logging && Status != getState(praefix + SzenenName + ".is_activ").val) {
              
              Dominik F. 1 Reply Last reply Reply Quote 1
              • Dominik F.
                Dominik F. @paul53 last edited by

                @paul53

                Super, jetzt funktioniert es.
                Könntest du mir kurz erklären wie du darauf gekommen bist diese 'Änderung vorzunehmen?
                Sorry wenn ich so viel frage, ich möchte das verstehen damit ich in Zukunft selber Lösungen finden kann.

                paul53 1 Reply Last reply Reply Quote 0
                • paul53
                  paul53 @Dominik F. last edited by

                  @Dominik-F sagte:

                  diese 'Änderung vorzunehmen?

                  Zusätzlich zu logging muss der neue Status sich vom im Datenpunkt enthalten Wert unterscheiden, damit log() ausgeführt wird.

                  Dominik F. 1 Reply Last reply Reply Quote 0
                  • Dominik F.
                    Dominik F. @paul53 last edited by

                    @paul53

                    Ich danke dir für deine Erklärung. Ich habe nun den Datenpunkt Button durch einen State ersetzt und versucht alle Datenpunkte damit zu schalten. Das funktioniert soweit auch nur habe ich jetzt noch 2 Probleme.
                    Das logging zeigt für aktiv richtig an, für false wird 4x inaktiv angezeigt bei 4 states die auf false gesetzt werden.
                    2tes Problem ist, das ich ja grundsätzlich möchte, dass wenn wenn ich den aktivieren state auf true setze, die szene aktiviert wird und alle states auf true gesetzt werden und andersherum eben auf false. Die states werden nun aber unabhängig davon geschaltet. Sind alle states auf true und ich schalte den Datenpunkt aktivieren auf true, sollte eigentlich nichts passieren, es wird jedoch alles auf false gesetzt. Hast du da noch eine Idee?

                    
                    //Grundeinstellungen
                    const logging = true; // Logs ausgeben
                    const praefix = "javascript.0.Szenen."; //Grundpfad für Script DPs - Muß innerhalb javascript.x sein.
                    
                    const SzeneData = [];
                    const SzeneID = [];
                    
                    //Name der Szenen eingeben
                    const SzenenName = "Chillen";
                    
                    //Hier die IDs eingeben
                    SzeneID[0] = "zigbee.0.f0d1b8000010bb79.state";  //Stehlampe
                    SzeneID[1] = "zigbee.0.7cb03eaa0a068b8d.state";  //Laterne
                    SzeneID[2] = "zigbee.0.7cb03eaa00b1b716.state";  //Sideboard
                    SzeneID[3] = "zigbee.0.7cb03eaa0a06f6b0.state";  //Vitrine
                    
                    //Schleife durch die ID's und Werte
                    for (let x = 0; x < SzeneID.length; x++) {
                        SzeneData[x] = getState(SzeneID[x]).val;
                    };
                    
                    //Datenpunkte erstellen
                    createState(praefix + SzenenName + ".activate", false, { name: "Szene aktivieren/deaktivieren", role: "state" });
                    createState(praefix + SzenenName + ".is_activ", { name: "is acitv?", role: "indicator" });
                    
                    //Ab hier eigentliches Skript
                    function Szene() {
                        let Status = true;
                        for (let x = 0; x < SzeneData.length; x++) {
                            if (!SzeneData[x]) Status = false;
                        }
                        if (logging && Status != getState(praefix + SzenenName + ".is_activ").val) {
                            if (Status) log("Szene " + SzenenName + " aktiv");
                            else log("Szene " + SzenenName + " inaktiv");
                        }
                        setState(praefix + SzenenName + ".is_activ", Status);
                    
                        // Szene einschalten/ausschalten
                        on({ id: praefix + SzenenName + ".activate", change: "any" }, function (obj) {
                            for (let x = 0; x < SzeneID.length; x++) {
                                if (obj.newState.val && praefix + SzenenName + ".is_activ") { setState(SzeneID[x], false); }
                                else { setState(SzeneID[x], true); }
                            }
                        });
                    };
                    Szene();
                    for (let x = 0; x < SzeneID.length; x++) { //Trigger in Schleife erstellen
                        on(SzeneID[x], function (dp) { // triggert bei Wertänderung
                            SzeneData[x] = dp.state.val;
                            Szene();
                        });
                    };
                    
                    
                    paul53 1 Reply Last reply Reply Quote 0
                    • paul53
                      paul53 @Dominik F. last edited by paul53

                      @Dominik-F sagte:

                      wenn wenn ich den aktivieren state auf true setze, die szene aktiviert wird und alle states auf true gesetzt werden und andersherum eben auf false.

                      Einen Trigger darf man nicht innerhalb einer Funktion definieren, weil dann bei jedem Aufruf der Funktion eine weiterer Trigger mit der gleichen Funktionalität erzeugt und so das System irgendwann überlastet wird. Außerhalb der Funktion (z.B. am Ende des Scripts):

                      // Szene einschalten/ausschalten
                      on(praefix + SzenenName + ".activate", function (obj) { // triggert bei Wertänderung
                          for (let x = 0; x < SzeneID.length; x++) {
                              setState(SzeneID[x], obj.state.val);
                          }
                      });
                      
                      Dominik F. 1 Reply Last reply Reply Quote 1
                      • Dominik F.
                        Dominik F. @paul53 last edited by

                        @paul53

                        Es funktioniert 🙂 Vielen Dank mal wieder. Ich glaube ich muss mir das Thema Trigger nochmal genauer anschauen
                        Hast du auch noch eine Idee zu den Logs?

                        paul53 1 Reply Last reply Reply Quote 0
                        • paul53
                          paul53 @Dominik F. last edited by

                          @Dominik-F sagte:

                          Hast du auch noch eine Idee zu den Logs?

                          Bei Szenenwechsel werden 4 Trigger ausgelöst und somit 4 mal die Funktion aufgerufen. Um den Funktionsaufruf bei gewolltem Szenenwechsel zu vermeiden, kann man die Quelle auswerten. Versuche mal

                          for (let x = 0; x < SzeneID.length; x++) { //Trigger in Schleife erstellen
                              on(SzeneID[x], function (dp) { // triggert bei Wertänderung
                                  SzeneData[x] = dp.state.val;
                                  if(dp.state.from != 'system.adapter.javascript.' + instance) Szene();
                              });
                          };
                          
                          Dominik F. 1 Reply Last reply Reply Quote 0
                          • Dominik F.
                            Dominik F. @paul53 last edited by

                            @paul53

                            Bevor ich das versuche hab ich noch eine Frage. Wieso passiert das ganze nur beim ausschalten der Szene? Beim einschalten wird nur ein Log ausgelöst.

                            paul53 1 Reply Last reply Reply Quote 0
                            • paul53
                              paul53 @Dominik F. last edited by

                              @Dominik-F sagte:

                              Wieso passiert das ganze nur beim ausschalten der Szene?

                              Gute Frage. Ich vermute, dass

                                  setState(praefix + SzenenName + ".is_activ", Status);
                              

                              unterschiedlich lange benötigt, bis der richtige Wert bei der Abfrage

                                  if (logging && Status != getState(praefix + SzenenName + ".is_activ").val) {
                              

                              zurück geliefert wird. Oder die Trigger reagieren unterschiedlich schnell auf den Wechsel ?

                              Dominik F. 1 Reply Last reply Reply Quote 0
                              • Dominik F.
                                Dominik F. @paul53 last edited by

                                @paul53

                                ja, Gefühlt schalten alle states gleichzeitig ein, aber unterschiedlich aus bzw. mit leichter Verzögerung.

                                paul53 1 Reply Last reply Reply Quote 0
                                • paul53
                                  paul53 @Dominik F. last edited by

                                  @Dominik-F sagte:

                                  unterschiedlich aus bzw. mit leichter Verzögerung.

                                  Um Laufzeitprobleme bei Verwendung von getState() zu vermeiden, sollte man besser eine Variable verwenden.

                                  //Ab hier eigentliches Skript
                                  var lastState = getState(praefix + SzenenName + ".is_activ").val;
                                  function Szene() {
                                      let Status = true;
                                      for (let x = 0; x < SzeneData.length; x++) {
                                          if (!SzeneData[x]) Status = false;
                                      }
                                      if (Status != lastState) {
                                          if(logging) {
                                              if (Status) log("Szene " + SzenenName + " aktiv");
                                              else log("Szene " + SzenenName + " inaktiv");
                                          }
                                          setState(praefix + SzenenName + ".is_activ", Status, true);
                                      }
                                      lastState = Status;
                                  }
                                  
                                  1 Reply Last reply Reply Quote 1
                                  • Dominik F.
                                    Dominik F. last edited by

                                    Super, jetzt funktioniert wirklich alles 🙂 Ich vermute das liegt daran, dass die states den Befehl mit leichter Verzögerung untereinander erhalten?

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

                                    Support us

                                    ioBroker
                                    Community Adapters
                                    Donate

                                    572
                                    Online

                                    31.9k
                                    Users

                                    80.2k
                                    Topics

                                    1.3m
                                    Posts

                                    javascript
                                    2
                                    17
                                    534
                                    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