Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. Timeout in JS einbinden

    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

    Timeout in JS einbinden

    This topic has been deleted. Only users with topic management privileges can see it.
    • OliverIO
      OliverIO @ubecker last edited by OliverIO

      @ubecker

      keine ahnung.
      du hattest ja nur geschrieben, hier die entsprechenden befehle eintragen und das habe ich getan.
      warum und wieso weiß ich ja nicht.

      hier die Hilfeseiten dazu
      https://developer.mozilla.org/en-US/docs/Web/API/Window/clearTimeout
      https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout

      M ubecker 2 Replies Last reply Reply Quote 0
      • M
        MCU @OliverIO last edited by

        @oliverio

        300*60*60*1000  sind mehr als 5Stunden?
        
        300*60*1000 -> 5Std
        
        OliverIO 1 Reply Last reply Reply Quote 0
        • Meister Mopper
          Meister Mopper @ubecker last edited by

          @ubecker sagte in Timeout in JS einbinden:

          @oliverio
          danke, so einfach?
          Hatte das in blockly gemacht und als JS augegeben. Da sah das sehr komplex aus.

          Dafür kannste auch KI verwenden, in vielen Fällen übersetzt sie die Blockly gut in JS. Ob es dann auch ressourcenschonend ist, steht auf einem anderen Blatt (dafür bracht es Profis).

          1 Reply Last reply Reply Quote 0
          • ubecker
            ubecker @OliverIO last edited by

            @oliverio
            alles ok, mir ging es nur um die syntax zu den Befehlen. Hab das nirgendwo gefunden.
            und danke für die links
            Zur weiteren Info:
            ich teste mittels Array Werte von (ca 20) Heizkörperventilen
            Wenn die Raumtemperatur abfällt öffnen die Ventile = Energieanforderung.
            Dann schalte ich die Heizung ein
            Der Timeout macht nur eine Verzögerung des ausschalten der Heizung

            OliverIO 2 Replies Last reply Reply Quote 0
            • OliverIO
              OliverIO @MCU last edited by

              @mcu

              ah ja, einmal 60* zuviel

              1 Reply Last reply Reply Quote 0
              • OliverIO
                OliverIO @ubecker last edited by

                @ubecker

                zunächst mal durch ki formatiert und erklärt

                Gerne! Hier ist dein Skript strukturiert, korrekt eingerückt und mit Kommentaren erklärt. Es handelt sich um ein JavaScript-Skript für ioBroker (Blockly/JavaScript Adapter), das prüft, ob die Heizungsanforderung durch verschiedene Quellen hoch genug ist, um den Heizkessel einzuschalten – oder nach 5 Stunden auszuschalten.


                ✨ Formatierter und erklärter Code

                // 🔥 Heizung ein-/ausschalten bei Energieanforderung
                
                const ids = 'javascript.0.Array_IDs_Heizung_level'; // Array mit allen Level-IDs
                const ID_Liste_Level = getState(ids).val;           // Liest die Array-IDs aus dem Datenpunkt
                const level_value = 20.1;                            // Schwellenwert für Aktivierung der Heizung
                
                // ⏱ Trigger auf Änderungen in einem der Level-Werte
                on({ id: [].concat(ID_Liste_Level), change: 'ne' }, async (obj) => {
                    let value = obj.state.val;
                    let oldValue = obj.oldState.val;
                
                    // 🔁 Schleife über alle Heiz-Level IDs
                    let x_end = ID_Liste_Level.length - 1;
                    let x_inc = 1;
                    let gesamt_value = 0.0;
                    let timeout;
                
                    if (x_end < 0) {
                        x_inc = -x_inc;
                    }
                
                    for (let x = 0; x_inc >= 0 ? x <= x_end : x >= x_end; x += x_inc) {
                        gesamt_value += getState(ID_Liste_Level[x]).val;
                    }
                
                    // ✅ Wenn die Gesamtleistung über dem Schwellwert liegt
                    if (gesamt_value >= level_value) {
                        // Heizung aktivieren
                        setState('javascript.0.Heizung_Kessel_aktiv', true, true);
                
                        // Eventuell vorhandenen Ausschalt-Timer löschen
                        clearTimeout(timeout);
                    } else {
                        // ❄️ Heizung erst nach 5 Stunden deaktivieren
                        timeout = setTimeout(() => {
                            setState('javascript.0.Heizung_Kessel_aktiv', false, true);
                        }, 300 * 60 * 1000); // 300 Minuten = 5 Stunden
                    }
                
                    // 🧾 Debug-Ausgabe
                    console.log(gesamt_value);
                });
                

                🧠 Was macht das Skript genau?

                Abschnitt Funktion
                getState(ids).val Holt die Liste der IDs, deren Werte überwacht werden sollen
                on({...}) Reagiert auf jede Änderung eines Werts in dieser Liste
                for-Schleife Summiert alle aktuellen Werte der IDs (z. B. Heizkreise)
                if gesamt_value >= ... Wenn genug Anforderung vorhanden ist → Heizung an
                else mit setTimeout Sonst: nach 5 Stunden (300 Minuten) → Heizung aus
                clearTimeout(timeout) Wenn vorher ein Ausschalten geplant war, aber jetzt wieder Anforderung kommt, wird der Timer gelöscht

                🛠 Hinweise

                • timeout ist aktuell lokal in der Funktion definiert – wird aber bei jedem Trigger neu gesetzt. Damit der Ausschalt-Timer persistiert, muss timeout außerhalb des Event-Handlers deklariert werden (sonst funktioniert clearTimeout() nicht wie gewünscht).

                Mögliche Verbesserung:

                let timeout; // globale Variable außerhalb des Event-Handlers
                
                on({...}) {
                    ...
                }
                

                Wenn du willst, kann ich das für dich gleich verbessern.

                OliverIO 1 Reply Last reply Reply Quote 0
                • OliverIO
                  OliverIO @OliverIO last edited by

                  nächster schritt

                  Perfekt! Hier ist dein Skript mit korrekt implementiertem Timeout-Handling, sodass clearTimeout(timeout) wie gewünscht funktioniert und nicht bei jedem Trigger-Ereignis verloren geht:


                  ✅ Finale Version mit persistentem Timeout

                  // 🔥 Heizung ein-/ausschalten bei Energieanforderung
                  
                  const ids = 'javascript.0.Array_IDs_Heizung_level';       // Datenpunkt mit Array von Level-IDs
                  const level_value = 20.1;                                  // Schwellenwert zur Aktivierung der Heizung
                  const ID_Liste_Level = getState(ids).val;                  // Array der zu überwachenden IDs
                  
                  let timeout = null; // ⏱ Timeout-Variable global definieren
                  
                  // 📡 Trigger bei jeder Änderung eines Wertes in der Liste
                  on({ id: [].concat(ID_Liste_Level), change: 'ne' }, async (obj) => {
                      let gesamt_value = 0.0;
                  
                      // 🔁 Summiere alle aktuellen Werte
                      for (let i = 0; i < ID_Liste_Level.length; i++) {
                          let val = getState(ID_Liste_Level[i]).val;
                          gesamt_value += val;
                      }
                  
                      // ✅ Wenn Schwelle erreicht oder überschritten → Heizung AN
                      if (gesamt_value >= level_value) {
                          setState('javascript.0.Heizung_Kessel_aktiv', true, true);
                  
                          // ⛔ Bereits laufenden Ausschalt-Timer abbrechen
                          if (timeout !== null) {
                              clearTimeout(timeout);
                              timeout = null;
                          }
                      }
                      // ❄️ Wenn unter Schwelle → Heizung AUS (nach 5 Stunden)
                      else {
                          if (timeout === null) {
                              timeout = setTimeout(() => {
                                  setState('javascript.0.Heizung_Kessel_aktiv', false, true);
                                  timeout = null; // Timer zurücksetzen
                              }, 300 * 60 * 1000); // 300 Minuten = 5 Stunden
                          }
                      }
                  
                      // 📋 Protokolliere aktuellen Summenwert
                      console.log('Gesamtanforderung:', gesamt_value);
                  });
                  

                  🧠 Vorteil der Änderung

                  Durch die globale timeout-Variable wird verhindert, dass mehrere setTimeout()-Aufrufe gleichzeitig laufen. Stattdessen gibt es genau einen Ausschalt-Timer, der bei Bedarf neu gesetzt oder gelöscht wird.

                  Wenn du möchtest, kann ich auch eine erweiterte Version mit Logging, Telegram-Benachrichtigung oder Visualisierung vorbereiten.

                  paul53 ubecker 2 Replies Last reply Reply Quote 0
                  • OliverIO
                    OliverIO @ubecker last edited by

                    @ubecker
                    das geht auch schon in der kostenlosen version mit chatgpt

                    ubecker 1 Reply Last reply Reply Quote 0
                    • paul53
                      paul53 @OliverIO last edited by paul53

                      @oliverio sagte: Durch die globale timeout-Variable wird verhindert, dass mehrere setTimeout()-Aufrufe gleichzeitig laufen.

                      Das ist bei analogen Vergleichswerten auch erforderlich, da andernfalls clearTimeout(timeout) nicht funktioniert.
                      Prinzip:

                          if (Vergleich von Analogwerten) {
                              setState('javascript.0.Heizung_Kessel_aktiv', true, true);
                              // ⛔ Bereits laufenden Ausschalt-Timer abbrechen
                              if (timeout) {
                                  clearTimeout(timeout);
                                  timeout = null;
                              }
                          } else if (!timeout) {
                              timeout = setTimeout(() => {
                                  setState('javascript.0.Heizung_Kessel_aktiv', false, true);
                              }, 300 * 60 * 1000); // 300 Minuten = 5 Stunden
                          }
                      
                      OliverIO 1 Reply Last reply Reply Quote 0
                      • OliverIO
                        OliverIO @paul53 last edited by

                        @paul53 das was copy/paste aus chatgpt

                        1 Reply Last reply Reply Quote 0
                        • ubecker
                          ubecker @OliverIO last edited by

                          @oliverio said in Timeout in JS einbinden:

                          nächster schritt

                          Perfekt! Hier ist dein Skript mit korrekt implementiertem Timeout-Handling, sodass clearTimeout(timeout) wie gewünscht funktioniert und nicht bei jedem Trigger-Ereignis verloren geht:


                          ✅ Finale Version mit persistentem Timeout

                          // 🔥 Heizung ein-/ausschalten bei Energieanforderung
                          
                          const ids = 'javascript.0.Array_IDs_Heizung_level';       // Datenpunkt mit Array von Level-IDs
                          const level_value = 20.1;                                  // Schwellenwert zur Aktivierung der Heizung
                          const ID_Liste_Level = getState(ids).val;                  // Array der zu überwachenden IDs
                          
                          let timeout = null; // ⏱ Timeout-Variable global definieren
                          
                          // 📡 Trigger bei jeder Änderung eines Wertes in der Liste
                          on({ id: [].concat(ID_Liste_Level), change: 'ne' }, async (obj) => {
                              let gesamt_value = 0.0;
                          
                              // 🔁 Summiere alle aktuellen Werte
                              for (let i = 0; i < ID_Liste_Level.length; i++) {
                                  let val = getState(ID_Liste_Level[i]).val;
                                  gesamt_value += val;
                              }
                          
                              // ✅ Wenn Schwelle erreicht oder überschritten → Heizung AN
                              if (gesamt_value >= level_value) {
                                  setState('javascript.0.Heizung_Kessel_aktiv', true, true);
                          
                                  // ⛔ Bereits laufenden Ausschalt-Timer abbrechen
                                  if (timeout !== null) {
                                      clearTimeout(timeout);
                                      timeout = null;
                                  }
                              }
                              // ❄️ Wenn unter Schwelle → Heizung AUS (nach 5 Stunden)
                              else {
                                  if (timeout === null) {
                                      timeout = setTimeout(() => {
                                          setState('javascript.0.Heizung_Kessel_aktiv', false, true);
                                          timeout = null; // Timer zurücksetzen
                                      }, 300 * 60 * 1000); // 300 Minuten = 5 Stunden
                                  }
                              }
                          
                              // 📋 Protokolliere aktuellen Summenwert
                              console.log('Gesamtanforderung:', gesamt_value);
                          });
                          

                          🧠 Vorteil der Änderung

                          Durch die globale timeout-Variable wird verhindert, dass mehrere setTimeout()-Aufrufe gleichzeitig laufen. Stattdessen gibt es genau einen Ausschalt-Timer, der bei Bedarf neu gesetzt oder gelöscht wird.

                          Wenn du möchtest, kann ich auch eine erweiterte Version mit Logging, Telegram-Benachrichtigung oder Visualisierung vorbereiten.


                          super; einzig was noch fehlt sind die Bedingungen wenn Heizug schon auf true steht braucht nicht wieder gesetzt zu werden, auch beim ausschalten. sind aber nur 2 if Bedingungen.

                          1 Reply Last reply Reply Quote 0
                          • ubecker
                            ubecker @OliverIO last edited by

                            @oliverio
                            kleiner Fehler in dem Script:
                            console.log('Gesamtanforderung:', gesamt_value);
                            funktioniert so nicht da erst ein String und dann eine Zahl.
                            Zahl nach String konvertieren oder einfach den String 'Gesamtanforderung:' weglassen

                            sonst alles ok, meine if Bedingung zum setzen hab ich auch eingebaut.

                            nochmals Danke.

                            M paul53 OliverIO 3 Replies Last reply Reply Quote 0
                            • M
                              MCU @ubecker last edited by

                              @ubecker sagte in Timeout in JS einbinden:

                              console.log('Gesamtanforderung:', gesamt_value);

                              console.log('Gesamtanforderung: '+ gesamt_value);
                              
                              1 Reply Last reply Reply Quote 0
                              • paul53
                                paul53 @ubecker last edited by

                                @ubecker sagte: funktioniert so nicht da erst ein String und dann eine Zahl.

                                Funktioniert, wenn das Komma durch ein Plus ersetzt wird.

                                1 Reply Last reply Reply Quote 1
                                • OliverIO
                                  OliverIO @ubecker last edited by OliverIO

                                  @ubecker sagte in Timeout in JS einbinden:

                                  console.log('Gesamtanforderung:', gesamt_value);

                                  wie gesagt, das skript ist nicht von mir überarbeitet worden, sondern von chatGPT
                                  nach Definition ist das richtig
                                  https://developer.mozilla.org/en-US/docs/Web/API/console/log_static
                                  https://nodejs.org/api/console.html#consolelogdata-args
                                  console.log nimmt 1 bis N parameter. jeder parameter wird gemäß typ so ausgegeben

                                  mit + wird automatisch von javascript der typ aus gesamt_value nach string gewandelt und dann das ergebnis angehängt.

                                  da scheint es im javascript adapter noch was geben
                                  hier die ausgabe aus der browser console
                                  4e69704f-ced3-4f57-b243-1db1d37289bd-image.png

                                  und aus der node repl (einfach node starten)
                                  d774bb97-a55f-42fd-a7be-ae1477382e26-image.png

                                  habe mal geschaut.
                                  da ist die typdefinition im javascript adapter nicht ganz korrekt.
                                  die console befehle kennen alle nur einen parameter.
                                  allerdings ist das auch nicht die priorität, ist ja eh nur für debugging
                                  https://github.com/ioBroker/ioBroker.javascript/blob/64c375ea0e0840f21a7cc12582c970022f061fa2/src/types.d.ts#L570

                                  P ubecker 2 Replies Last reply Reply Quote 0
                                  • P
                                    peterfido @OliverIO last edited by

                                    @oliverio Für solche Zeitspannen setze ich auf einen Datenpunkt, welcher minutiös heruntergezählt wird. Arbeitet man am ioBroker innerhalb der fünf Stunden, kann es sonst passieren, dass das Timeout verlorengeht.

                                    OliverIO 1 Reply Last reply Reply Quote 0
                                    • OliverIO
                                      OliverIO @peterfido last edited by

                                      @peterfido
                                      Besser:
                                      Den Ende timestamp in einem datenpunkt merken und dann regelmäßig prüfen, ob er erreicht wird. Bzw. der datenpunkt existiert nur falls der Adapter neu gestartet wird, damit man wieder neu aufsetzen kann.
                                      Dann schreibt man nicht so oft in der Datenbank herum.

                                      1 Reply Last reply Reply Quote 0
                                      • P
                                        peterfido last edited by

                                        @oliverio Der Schreibzyklen wegen vielleicht schon. Darüber habe ich mir zu Raspi-Zeiten tatsächlich Gedanken gemacht.Also, wie so oft, ein "kommt darauf an".

                                        1 Reply Last reply Reply Quote 0
                                        • ubecker
                                          ubecker @OliverIO last edited by

                                          @oliverio said in Timeout in JS einbinden:

                                          allerdings ist das auch nicht die priorität, ist ja eh nur für debugging

                                          genau.

                                          @oliverio said in Timeout in JS einbinden:

                                          Den Ende timestamp in einem datenpunkt merken und dann regelmäßig prüfen, ob er erreicht wird. Bzw. der datenpunkt existiert nur falls der Adapter neu gestartet wird, damit man wieder neu aufsetzen kann.
                                          Dann schreibt man nicht so oft in der Datenbank herum

                                          hier eigentlich unkritisch. Dann bleibt die Heizung weitere 5 Std. an.
                                          ich lass es erst mal beim normalen Teimout und werde das beobachten.

                                          danke an alle

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

                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          955
                                          Online

                                          31.7k
                                          Users

                                          79.9k
                                          Topics

                                          1.3m
                                          Posts

                                          6
                                          24
                                          102
                                          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