Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. In einer Funktion auf Änderung eines Datenpunkts warten

    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

    In einer Funktion auf Änderung eines Datenpunkts warten

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

      Hallo zusammen,

      ich stehe gerade auf dem Schlauch: Innerhalb einer Funktion, die über on() getriggert wird, nutze ich ein setState(), um einen Aktor zu starten. Als nächstes soll ein Datenpunkt überwacht werden und erst, wenn dieser auf einen bestimmten Wert geht, soll die Funktion weiter abgearbeitet werden. Ist sowas überhaupt möglich?

      Das mit dem while() im folgenden Code ist Quatsch, aber vielleicht ist das verständlicher :

      function garageDoorOpen() {
          if(getState(dpGarageDoorState).val == 0 || getState(dpGarageDoorState).val == 2) {
              setState(dpGarageDoorCommand, 1);
              setState(dpInstanz + dpGarageDoorStatus, txtGarageDoorOpen);
              while(getState(dpGarageDoorProcess).val === 1) {
                  // An dieser Stelle soll die Funktion solange warten,
                  // bis "getState(dpGarageDoorProcess).val === 1" ist
              }
              setState(dpInstanz + dpGarageDoorStatus, txtGarageDoorIsOpened);
              setState(dpInstanz + dpGarageDoorOpen, false);
          }
      }
      
      on ({ id: dpInstanz + dpGarageDoorOpen,  change: 'any', val: true }, function () { garageDoorOpen();  });
      

      Viele Grüße
      Levy

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

        @levyko sagte in In einer Funktion auf Änderung eines Datenpunkts warten:

        dpGarageDoorProcess

        Warum in die Funktion garageDoorOpen?
        Pack doch den DP als on()-Trigger und frage den entsprechenden Wert ab und setz dann die anderen Werte.

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

          @levyko

          warten in einer schleife ist nie gut
          aber du hast hier dann 2 trigger

          1. den du schon umgesetzt hast und den
          2. wenn sich dpGarageDoorProcess (wieder) ändert
            da wäre dann der weitere teil deiner Verarbeitung

          Darüber hinaus kannst du deinen code optimieren.
          wenn der trigger aufgerufen wird, wird der wert ja bereits mitgeliefert, dann musst du den nicht nochmal per getstate abfragen
          https://github.com/ioBroker/ioBroker.javascript/blob/master/docs/en/javascript.md#on---subscribe-on-changes-or-updates-of-some-state

          ich gehe mal davon aus, das du die garage öffnen willst und dann wenn sich das tor zu ende bewegt hat, dann nochmal den richtigen status setzen
          dann wären die statusübergänge wie folgt
          Closed->Opening->Opened->Closing->Closed

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

            @levyko
            Welche Werte (mit welcher Bedeutung) kann der DP dpGarageDoorState annehmen? Wahrscheinlich genügt es, diesen DP als weiteren Trigger zu verwenden, etwa so:

            var doorState = getState(dpGarageDoorState).val;
            
            on ({id: dpInstanz + dpGarageDoorOpen, val: true}, function () {
                if(doorState == 0 || doorState == 2) {
                    setState(dpGarageDoorCommand, 1);
                    setState(dpGarageDoorStatus, txtGarageDoorOpen, true);
                }
            });
            
            on(dpGarageDoorState, function(dp) {
                doorState = dp.state.val;
                if(doorState == 1) { // is Opened?
                    setState(dpGarageDoorStatus, txtGarageDoorIsOpened, true);
                    setState(dpGarageDoorOpen, false, true);
                }
            });
            

            Anmerkung: Wenn dpInstanz = 'javascript.N.' ist, kann bei setState(id, val, true) die verkürzte ID verwendet werden. Nur on(pattern, cb) benötigt die vollständige ID. Das Rücksetzen des Taster-DP (Zeile 14) ist normalerweise nicht nötig.

            1 Reply Last reply Reply Quote 0
            • T
              ticaki Developer @LevyKo last edited by ticaki

              async function garageDoorOpen() {
                  if(getState(dpGarageDoorState).val == 0 || getState(dpGarageDoorState).val == 2) {
                      setState(dpGarageDoorCommand, 1);
                      setState(dpInstanz + dpGarageDoorStatus, txtGarageDoorOpen);
                      while(getState(dpGarageDoorProcess).val === 1) {
                          await sleep(500)
                      }
                      setState(dpInstanz + dpGarageDoorStatus, txtGarageDoorIsOpened);
                      setState(dpInstanz + dpGarageDoorOpen, false);
                  }
              }
              

              Ich stimme dem Rest zu, nur weils geht ist es keine gute Idee 🙂 Was passiert eigentlich wenn du dich umentscheidest?

              1 Reply Last reply Reply Quote 0
              • LevyKo
                LevyKo last edited by

                Erst einmal vielen Dank für die Antworten und Denkanstöße. Ich habe es jetzt, wie von Euch vorgeschlagen, mit vier on()'s realisiert. Hier mal das komplette Script:

                var dpGarageDoorOpen    = '0_userdata.0.Trigger.TriggerGarageDoorOpen';
                var dpGarageDoorClose   = '0_userdata.0.Trigger.TriggerGarageDoorClose';
                var dpGarageDoorStatus  = '0_userdata.0.Trigger.TriggerGarageDoorStatus';
                var dpGarageDoorState   = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_STATE';
                var dpGarageDoorCommand = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_COMMAND';
                var dpGarageDoorProcess = 'hm-rpc.0.00XXXXXXXXXXF7.1.PROCESS';
                
                on ({ id: dpGarageDoorOpen, change: 'ne', val: true }, function () {
                    if(getState(dpGarageDoorState).val === 0 || getState(dpGarageDoorState).val === 2 || getState(dpGarageDoorState).val === 3) {
                        setState(dpGarageDoorCommand, 1);
                    } else {
                        setState(dpGarageDoorOpen, false);
                        setState(dpGarageDoorClose, false);
                    }
                });
                
                on ({ id: dpGarageDoorClose, change: 'ne', val: true }, function () {
                    if(getState(dpGarageDoorState).val === 1 || getState(dpGarageDoorState).val === 2 || getState(dpGarageDoorState).val === 3) {
                        setState(dpGarageDoorCommand, 3);
                    } else {
                        setState(dpGarageDoorOpen, false);
                        setState(dpGarageDoorClose, false);
                    }
                });
                
                on ({ id: dpGarageDoorProcess, change: 'ne' }, function () {
                    if(getState(dpGarageDoorOpen).val == true) {
                        if(getState(dpGarageDoorProcess).val === 1) setState(dpGarageDoorStatus, 'wird geöffnet');
                    }
                    if(getState(dpGarageDoorClose).val == true) {
                        if(getState(dpGarageDoorProcess).val === 1) setState(dpGarageDoorStatus, 'wird geschlossen');
                    }
                });
                
                on ({ id: dpGarageDoorState, change: 'ne' }, function () {
                    if(getState(dpGarageDoorState).val === 0) {
                        setState(dpGarageDoorStatus, 'geschlossen');
                        setState(dpGarageDoorOpen, false);
                        setState(dpGarageDoorClose, false);
                        toLog('Das Garagentor wurde geschlossen');
                    }
                    if(getState(dpGarageDoorState).val === 1) {
                        setState(dpGarageDoorStatus, 'offen');
                        setState(dpGarageDoorOpen, false);
                        setState(dpGarageDoorClose, false);
                        toLog('Das Garagentor wurde geöffnet');
                    }
                });
                

                Da kann ich sicherlich noch einiges optimieren, aber so läuft es jetzt ersteinmal. Rein muss für den normalen Betrieb noch die Abfrage nach Blockade und Drücken von Stop.

                Hintergrund ist, dass bisher für VIS einfach direkt auf die Datenpunkte des HmIP-MOD-HO gegangen bin. Das funktionierte soweit auch. Nun wird die Garage aber als separate Zone in unsere Alarmanlage integriert und ich muss ein "versehentliches" Öffnen durch VIS bei Scharfschaltung verhindern. Das kann ich über das Script alles abfangen. Zusätzlich kann ich nun über Alexa vom Auto aus (nennt sich bei Audi "integrated Alexa" oder so) das Tor auf- und zufahren. Daher die beiden Trigger-Datenpunkte.

                Viele Grüße
                Levy

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

                  @levyko sagte: Da kann ich sicherlich noch einiges optimieren

                  Allerdings.

                  const dpGarageDoorOpen    = '0_userdata.0.Trigger.TriggerGarageDoorOpen';
                  const dpGarageDoorClose   = '0_userdata.0.Trigger.TriggerGarageDoorClose';
                  const dpGarageDoorStatus  = '0_userdata.0.Trigger.TriggerGarageDoorStatus';
                  const dpGarageDoorState   = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_STATE';
                  const dpGarageDoorCommand = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_COMMAND';
                  // var dpGarageDoorProcess = 'hm-rpc.0.00XXXXXXXXXXF7.1.PROCESS';
                  
                  var doorState = getState(dpGarageDoorState).val;
                  
                  on ({id: dpGarageDoorOpen, change: 'ne', val: true}, function () {
                      if(doorState != 1) {
                          setState(dpGarageDoorCommand, 1);
                          setState(dpGarageDoorStatus, 'wird geöffnet', true);
                      }
                      setState(dpGarageDoorOpen, false, true);
                  });
                   
                  on ({id: dpGarageDoorClose, change: 'ne', val: true }, function () {
                      if(doorState > 0) {
                          setState(dpGarageDoorCommand, 3);
                          setState(dpGarageDoorStatus, 'wird geschlossen', true);
                      }
                      setState(dpGarageDoorClose, false, true);
                  });
                   
                  on (dpGarageDoorState, function (dp) { // triggert bei Wertänderung
                      doorState = dp.state.val;
                      let msg = '';
                      if(doorState === 0) {
                          msg = 'geschlossen';
                      } else if(doorState === 1) {
                          msg = 'offen';
                      }
                      if(msg) {
                          setState(dpGarageDoorStatus, msg, true);
                          log('Das Garagentor ist ' + msg);
                      }
                  });
                  

                  Ist toLog() eine globale Funktion?

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

                    @paul53
                    Danke für die Überarbeitung. Das sieht doch wesentlich kompakter aus 👍

                    Ja, toLog() ist eine globale Funktion, die mir eine Aktivitätsliste füllt und gleichzeitig einen Log-Eintrag erstellt.

                    Da neben der Steuerung des Tors in dem eigentlichen Script noch die Regelung eines Lüfters drin ist, hier mal der aktuelle Stand des gesamten Scripts:

                    /*
                    **
                    ** Steuerung Garage
                    **
                    */
                    
                    var cronVal               = '*/15 * * * *';
                    var numMinDuration        = 30;
                    
                    var dpAussenTemperatur    = 'hm-rpc.0.00XXXXXXXXXXEF.1.ACTUAL_TEMPERATURE';
                    var dpAussenFeuchtigkeit  = 'hm-rpc.0.00XXXXXXXXXXEF.1.HUMIDITY';
                    var dpGarageFeuchtigkeit  = 'hm-rpc.0.00XXXXXXXXXX5F.1.HUMIDITY';
                    var dpGarageLuefter       = 'hm-rpc.0.00XXXXXXXXXX9D.3.STATE';
                    
                    const dpGarageDoorOpen    = '0_userdata.0.Trigger.TriggerGarageDoorOpen';
                    const dpGarageDoorClose   = '0_userdata.0.Trigger.TriggerGarageDoorClose';
                    const dpGarageDoorStatus  = '0_userdata.0.Trigger.TriggerGarageDoorStatus';
                    const dpGarageDoorState   = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_STATE';
                    const dpGarageDoorCommand = 'hm-rpc.0.00XXXXXXXXXXF7.1.DOOR_COMMAND';
                    
                    var doorState = getState(dpGarageDoorState).val;
                    
                    /*
                    ** Create Datapoints
                    */
                    createState(dpGarageDoorOpen,   false, { name: 'TriggerGarageDoorOpen',   desc: 'TriggerGarageDoorOpen',   type: 'boolean', role: 'state' });
                    createState(dpGarageDoorClose,  false, { name: 'TriggerGarageDoorClose',  desc: 'TriggerGarageDoorClose',  type: 'boolean', role: 'state' });
                    createState(dpGarageDoorStatus,   '-', { name: 'TriggerGarageDoorStatus', desc: 'TriggerGarageDoorStatus', type: 'string',  role: 'value' });
                    
                    /*
                    ** Subscriptions
                    */
                    schedule(cronVal, function() {
                        if(getState(dpGarageLuefter).val === false) {
                            if(getState(dpGarageFeuchtigkeit).val > getState(dpAussenFeuchtigkeit).val) {
                                if(getState(dpAussenTemperatur).val > 5) {
                                    if(getState(dpAussenTemperatur).val < 20) {
                                        var numMilSecsDur = numMinDuration * 60000;
                                        var endTime = Date.now() + numMilSecsDur;
                                        setState(dpGarageLuefter, true);
                                        toLog('Garagenbelüftung eingeschaltet (Dauer: ' + numMinDuration + ' - Lf: ' + getState(dpGarageFeuchtigkeit).val + '%)');
                                        var sHandler = schedule(endTime, function () {
                                            setState(dpGarageLuefter, false);
                                            toLog('Garagenbelüftung ausgeschaltet (Lf: ' + getState(dpGarageFeuchtigkeit).val + '%)');
                                            clearSchedule(sHandler);
                                        });
                                    }
                                }
                            }
                        }
                    });
                     
                    on ({id: dpGarageDoorOpen, change: 'ne', val: true}, function () {
                        if(doorState != 1) {
                            setState(dpGarageDoorCommand, 1);
                            setState(dpGarageDoorStatus, 'wird geöffnet', true);
                        }
                        setState(dpGarageDoorOpen, false, true);
                    });
                     
                    on ({id: dpGarageDoorClose, change: 'ne', val: true }, function () {
                        if(doorState > 0) {
                            setState(dpGarageDoorCommand, 3);
                            setState(dpGarageDoorStatus, 'wird geschlossen', true);
                        }
                        setState(dpGarageDoorClose, false, true);
                    });
                     
                    on (dpGarageDoorState, function (dp) {
                        doorState = dp.state.val;
                        let msg = '';
                        if(doorState === 0) {
                            msg = 'geschlossen';
                        } else if(doorState === 1) {
                            msg = 'offen';
                        }
                        if(msg) {
                            setState(dpGarageDoorStatus, msg, true);
                            toLog('Das Garagentor ist ' + msg);
                        }
                    });
                    

                    Vielleicht kann der eine oder andere davon etwas gebrauchen.

                    Viele Grüße
                    Levy

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

                    Support us

                    ioBroker
                    Community Adapters
                    Donate

                    745
                    Online

                    31.8k
                    Users

                    80.0k
                    Topics

                    1.3m
                    Posts

                    5
                    8
                    356
                    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