Ankündigung

Einklappen
Keine Ankündigung bisher.

Rule: Timer ablaufen lassen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Rule: Timer ablaufen lassen

    Hallo,
    wie kann ich eine Rule mit einem Timer erzeugen?

    Ich möchte einen Button auf meiner Visu haben, welcher bei Betätigung der Wärmepumpe einen Befehl zur Warmwasserbereitung sendet und nach z.B. 30 Minuten bzw. bei erreichen der Zieltemperatur die veränderten Soll-WW-Werte wieder auf den Ausgangswert zurück stellt.

    Ich habe z.B. Mittags eine Stunde für die WW-Bereitung definiert. Rest des Tages ist die WW-Versorgung entweder komplett abgeschaltet oder auf einem niedrigeren Wert gesetzt. Wenn ich aber morgens dusche und meine Frau dann vormittags duschen will, ist kein WW mehr da, weil ja mittags erst nachgeheizt wird. Da wir im Regelfall beide Abends duschen, kommt es nicht sehr oft zu dem Szenario. Drum möchte ich das manuell bedienbar machen.

    #2
    Moin.
    Schnell mal nach "openhab rule timer" gesucht und das hier gefunden
    https://github.com/openhab/openhab/w...period-of-time

    hth,

    Stefan

    Kommentar


      #3
      Ja, sowas hab ich auch gefunden, aber ich will ja nicht 60 Minuten warten und dann erst das Warmwasser aktivieren, sondern das WW aktivieren und dann 60 Minuten warten und dann nach Ablauf der Zeit oder nach erreichen der Temperatur wieder was anderes ausführen.

      Müsste das dann in etwa so aussehen?

      Code:
      rule "auf Knopfdruck 60 Minuten Warmwasser aktiv"    
             when
                 Item Warmwasseranforderung changed
             then        
                 if(Warmwassertemperatur.state<40) {            
                     -- > schalte warmwasser aktiv und setze Warmwassertemp auf 45°C            
                     timer = createTimer(now.plusSeconds(3600)) [|                
                         --> schalte Warmwasser wieder aus und setze Warmwassertemp wieder zurück auf 28°C                  ]
                 }    
      end



      Aber wo füge ich die Abfrage ein, damit innerhalb der 60 Minuten ständig überprüft wird, ob das Warmwasser bereits warm genug ist? Ich will nicht auf die in der Heizung eingestellten Werte gehen, sondern das innerhalb der Rule abfragen können.
      Zuletzt geändert von halloween; 03.12.2015, 15:14.

      Kommentar


        #4
        Also wenn ich das richtig sehe, willst du zwei Endbedingungen gleichzeitig? _Spätestens_ nach 60 Minuten soll die Wassererwärmung enden _oder_ wenn das Wasser warm genug ist?

        Ich würde das über zwei Rules regeln, die eine zeitgesteuert:

        Code:
        sendCommand(Warmwasser, ON)
                        createTimer(now.plusMinutes(60))[|
                            sendCommand(Warmwasser, OFF)
        Die zweite temperaturgesteuert:

        Code:
        if (wassertemperatur > 60) sendCommand(Warmwasser, OFF)
        Dass der Timer dann nach 60 Minuten nochmal OFF sendet, sollte nicht schaden?

        Kommentar


          #5
          Das 2 mal off sollte nicht schaden, jedoch soll die temp natürlich nur innerhalb des 60 Minuten Timers überwacht werden. Wenn die Wärmepumpe mittags automatisch heizt, möchte ich da nicht mit openhab reinpfuschen.

          Kommentar


            #6
            Also für die zweite Rule als Startbedingung "when Item Warmwasser changed"? Dann wird diese ja nur gestartet, wenn du explizit "sendCommand(Warmwasser, ON)" aufgerufen hast. Soweit ich dein System überblicke (was ich nicht tue, weil ich's ja gar nicht kenne ;-) ).

            Kommentar


              #7
              Nein, als zweite Rule sowas in der Art:

              Code:
              [FONT=courier new]when
                  warmwassertemperatur > 60°C
              then
                  if warmwassertimer ungleich null
                      beende warmwasserbereitung bzw. setze warmwassertimer auf null
                      und setze veränderte temp-werte wieder zurück[/FONT]

              Die Frage ist jetzt: Wird während der 60 Minuten der ersten rule auch die zweite rule ausgeführt? Würde das so klappen?

              Der Timer läuft ja nur, wenn ich die WW-Bereitung manuell angestoßen habe. Wenn die Wärmepumpe nach Programm heizt, gibts den nicht.
              Zuletzt geändert von halloween; 03.12.2015, 22:16.

              Kommentar


                #8
                Während der 60 Minuten läuft natürlich das ganze Regelwerk weiter, sonst hätte der Timer ja gar keinen Sinn und du könntest eine Warteschleife einbauen, die das ganze System für 60 Min. pausieren lässt...

                Kommentar


                  #9
                  Da openHAB stateless ist, spielt es tatsächlich (fast) keine Rolle, was alles an rules oder Timern oder sonstwas parallel abläuft. Fast deshalb, weil es natürlich bei einem hohen Grad an Parallelität zu Timingproblemen kommen könnte, aber das ist eher theoretisch.

                  Zwei Rules zum Abschalten sind sicher sinnvoll. Wichtig ist natürlich, dass Du den Timer auch einer Variablen zuweist:
                  Code:
                  import org.joda.time.DateTime
                  
                  var Timer myTimer=null
                  
                  rule "Auto-Off"
                  when
                      Item Warmwassertemperatur changed
                  then
                      if(Warmwassertemperatur.state>60 && myTimer!=null) {
                          myTimer.cancel                            // myTimer abbrechen
                          myTimer=null                              // und löschen
                          Warmwasser.sendCommand(OFF)               // schalte Warmwasser wieder aus
                          WarmwasserSoll.sendCommand(28)            // und setze Warmwassertemp wieder zurück auf 28°C
                      }
                  end
                    
                  rule "auf Knopfdruck 60 Minuten Warmwasser aktiv"
                  when
                      Item Warmwasseranforderung changed
                  then
                      if(Warmwassertemperatur.state<40) {
                          if(myTimer==null) {
                              Warmwasser.sendCommand(ON)           // schalte warmwasser aktiv
                              WarmwasserSoll.sendCommand(45)       // und setze Warmwassertemp auf 45°C
                              myTimer = createTimer(now.plusHours(1)) [| {
                                  Warmwasser.sendCommand(OFF)      // schalte Warmwasser wieder aus
                                  WarmwasserSoll.sendCommand(28)   // und setze Warmwassertemp wieder zurück auf 28°C
                              }
                              ]
                          }
                     }
                  end
                  Der Name von Variablen sollte möglichst nicht identisch mit einem Schlüsselwort sein (auch wenn die Schreibweise hier den Unterschied macht, das Fehlerpotential ist hoch)
                  Weiterhin muss die Variable außerhalb der Rules und am Beginn des Rulefiles (also vor der ersten Rule) definiert sein, sonst ist sie nicht in allen beteiligten Rules bekannt.
                  Falls Du mit mehreren Rule-Files arbeiten möchtest, müssen alle Rules, die auf gemeinsame Variablen zugreifen sollen auch in einem Rule-File stehen.
                  Wenn der Timer abgelaufen ist, wird er automatisch geleert, aber bei vorzeitigem Abbruch sollte die Variable zurückgesetzt werden, schon damit die Rule nicht unnötig weiterhin ausgeführt wird, obwohl die Heizperiode bereits beendet wurde.

                  Kommentar


                    #10
                    Super! Danke!

                    Ein paar Fragen noch:

                    *)
                    Du schreibst, die Variable muß auch außerhalb der rule definiert sein. Wo denn noch ausser im rule-File?

                    *)
                    Kann ich den Stand eines Timers auch als Bedingung für eine rule hernehmen oder nur dessen Zustand, 0 bzw. aktiv?
                    Also wenn ich schreibe

                    when var mytimer changed then...

                    wird dann nur erkannt, ob der timer aktiv oder auf null steht oder wird da auch jede Sekunde erkannt, dass sich der Timer ändert, wenn er runterzählt?

                    Ist das so eigentlich richtig oder muss man da dann auch item mytimer oder was anderes schreiben?

                    Nachdem ich diese manuelle Warmwasseranforderung eigentlich sehr selten benötige, muss ja nicht bei jedem 1/10-Grad WW-Temp-Änderung die rule ausgeführt werden. Mir würde es besser gefallen, wenn die rule nur läuft, wenn der timer auch tatsächlich runterzählt.

                    Kommentar


                      #11
                      Hallo udo1toni,

                      hab mal eine Frage zum Speicher-Management von Java. Du schreibst
                      Code:
                      myTimer.cancel
                      myTimer=null
                      Also in C++ würde durch die zweite Zeile nur der Pointer auf null gesetzt und nicht der Speicher wieder freigegeben. Sorgt Java selbst dafür, dass der Speicher freigegeben wird, wenn man einen Pointer auf null setzt? Oder ist myTimer gar kein Pointer?

                      Kommentar


                        #12
                        Aaaalso...

                        Eine rule-Datei kann mehrere Rules beinhalten. Wenn eine Variable innerhalb einer Rule definiert wird, existiert sie nur genau während der Laufzeit dieser Rule, und nur innerhalb dieser einen Rule. Da abgefragt werden soll, ob der Timer läuft (bzw. existiert), muss die Variable hierzu außerhalb der Rule am Beginn der .rule-Datei definiert sein (meine Beispielrule sollte so direkt lauffähig sein, vielleicht habe ich noch einen import vergessen...)

                        Eine Rule kann durch eine cron-Definition getriggert werden, oder durch Zustandsänderungen von Items. Variablen können Rules meines Wissens nicht antriggern. Der Aufruf der Rule sollte eigentlich nicht allzuviel Last erzeugen. Wobei die noch elegantere Variante vermutlich wäre, bei Überschreiten der Temperatur zu triggern, also:
                        Code:
                         when
                            Item Warmwassertemperatur changed to 60
                        then
                            if(myTimer!=null) {
                        Ich hab allerdings keine Ahnung, ob das so funktioniert, abgesehen davon triggert sie, wenn, natürlich nur genau bei 60, aber sowohl bei Überschreiten wie Unterschreiten des Wertes.

                        ---

                        Vom Speichermanagement habe ich keinen blassen Schimmer. myTimer ist in meinem Beispiel eine Variable vom Typ Timer. Ob das einem Pointer entspricht, muss Dir jemand mit Ahnung beantworten. Das Konstrukt stellt lediglich sicher, dass die Variable den Inhalt null hat. Wenn die Variable getestet wird, ist der Zustand auf jeden Fall definiert.

                        Kommentar


                          #13
                          Zitat von bremer Beitrag anzeigen
                          Hallo udo1toni,

                          hab mal eine Frage zum Speicher-Management von Java. Du schreibst
                          Code:
                          myTimer.cancel
                          myTimer=null
                          Also in C++ würde durch die zweite Zeile nur der Pointer auf null gesetzt und nicht der Speicher wieder freigegeben. Sorgt Java selbst dafür, dass der Speicher freigegeben wird, wenn man einen Pointer auf null setzt? Oder ist myTimer gar kein Pointer?
                          Das dürfte dann ein fall für den Garbage Collector sein.

                          Ich hab allerdings keine Ahnung, ob das so funktioniert, abgesehen davon triggert sie, wenn, natürlich nur genau bei 60, aber sowohl bei Überschreiten wie Unterschreiten des Wertes.
                          Ich würde daher auf changed triggern und eine >= Abfrage in der Regel anschließen, das die Temperatur überhaupt genau 60° sein wird ist nicht besonders wahrscheinlich. Ich hab aber auch keine Ahnung, ob der Trigger auf 60° so funktionieren würde.

                          Kommentar


                            #14
                            Zitat von Jockel Beitrag anzeigen
                            Ich würde daher auf changed triggern und eine >= Abfrage in der Regel anschließen, das die Temperatur überhaupt genau 60° sein wird ist nicht besonders wahrscheinlich. Ich hab aber auch keine Ahnung, ob der Trigger auf 60° so funktionieren würde.
                            Weshalb ich es in #9 ja auch so vorgeschlagen hatte

                            Kommentar


                              #15
                              Hi, ich hänge mich da mal mit meiner Frage dran, da ich meinen Timer nicht wirklich gebacken bekomme. Die Ladeeinheit soll sich einschalten wenn UEBERGREIFEND_Laden auf ON wechselt und solange anbleiben bis wieder UEBERGREIFEND_Laden auf OFF geht und die Leistung unter 2500W. Wenn sie auf OFF ist, soll sie sich wieder einschalten wenn die Leistung über 2500W ist, ausschalten wenn die Lesitung unter -500W geht, allerdings in diesem Fall erst nach 5 Minuten. Hier der Code:
                              PHP-Code:
                              pre.cjk font-family"Droid Sans Fallback",monospace; }margin-bottom0.25cmline-height120%; }  // Ladeeinheit
                                
                              rule "Ladeeinheit"
                                 
                              import org.joda.time.DateTime  var Timer Timerladeeinheitnull
                                 
                                when   Item aktLeistungberechnet received update 
                              or
                                            
                              Item UEBERGREIFEND_Laden received update
                                then
                                            
                              if (UEBERGREIFEND_Laden.state=ON)
                                            {
                                            
                              sendCommand(UEBERGREIFEND_LadeeinheitON)
                                                             if(
                              Timerladeeinheit!=null) {
                                                         
                              Timerladeeinheit.cancel                           Timerladeeinheit null                       }             }               else
                                                        {
                                                         if (
                              aktLeistungberechnet.state 2500)
                                                                         {
                                                                            
                              sendCommand(UEBERGREIFEND_LadeeinheitON)
                                                                             if(
                              Timerladeeinheit!=null) {
                                                     
                              Timerladeeinheit.cancel                             Timerladeeinheit null                                                                                         }
                                                                            }
                                                         if (
                              aktLeistungberechnet.state < -500)
                                                                           {
                                                                                
                              Timerladeeinheit createTimer(now.plusSeconds(300)) [|
                                                                                 
                              sendCommand(UEBERGREIFEND_LadeeinheitOFF)
                                                                                                   ]
                                                                            }
                                                             }
                                
                              end 

                              Kommentar

                              Lädt...
                              X