Ankündigung

Einklappen
Keine Ankündigung bisher.

OpenHab rules if/else

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

    OpenHab rules if/else

    Guten Abend zusammen,

    ich bekomme es nicht gebacken. Ich denke, dass die syntax falsch ist.

    Die If/else Statements funktionieren nicht. Die werden einfach missachtet. Es wird einfach der Inhalt ohne Überprüfung ausgeführt.


    Folgender Code, anschließend folgt die Erklärung:

    PHP-Code:
    rule "Licht Wohnen"

    when
        Item eg_pre_wohnen_LG1 changed   
    then  
        
    if (eg_pre_wohnen_LG1.state == OPEN && eg_wohnen_lux 200) {    
              if (
    hour 7  && hour 22) {
                   
    eg_licht_bad_komb.sendCommand(100)
               } 
        }
        
    Thread::sleep(5000)
        else {     
            
    eg_licht_wohn_led.sendCommand(0)
        }
    end 
    eg_pre_wohnen_LG1 : Präsenzmelder
    eg_wohnen_lux: Helligkeit in LUX des Präsenzmelder

    Danke!




    #2
    Hi!

    Die Syntax stimmt auf den ersten Blick nicht, da vermutest Du schon richtig. Dein Thread::sleep macht den if/else Block kaputt... Was soll das überhauaupt bewirken bzw. was willst Du genau erreichen?

    Kann der Präsenzmelder die helligkeitsabhängige Schaltung nicht von Haus aus? Was setzt Du ein? So eine Logik in eine Rule zu packen ist vielleicht "überdimensioniert"...
    Zuletzt geändert von ArPa; 16.09.2017, 20:20.
    Alle sagten: Das geht nicht. Dann kam einer, der wusste das nicht und hat's einfach gemacht.

    http://cleveres-heim.de

    Kommentar


      #3
      Moin,

      mein Präsenzmelder hat schon eine helligkeitsabhängige Schaltung. Ebenso eine Nachlaufzeit. Mit sleep wollte ich die Nachlaufzeit in OpenHab setzen. Ich würde das gerne alles in OpenHab regeln.

      Wenn ich Helligkeit und Zeiten vom PIR steuern lasse schaut es so aus:
      PHP-Code:
      rule "Licht Wohnen"

      when
          Item eg_pre_wohnen_LG1 changed   
      then  
          
      if (eg_pre_wohnen_LG1.state == OPEN) {    
                     
      eg_licht_bad_komb.sendCommand(100)
          }
          
      Thread::sleep(5000)
          else {     
              
      eg_licht_wohn_led.sendCommand(0)
          }
      end 
      Wie bekomme eine variable Nachlaufzeit in OpenHab? Weil in knx ist das ja immer statisch.

      Danke schonmal!

      Kommentar


        #4
        Ich würde einen Timer starten, der dann bei Ablauf das OFF schickt und bei Bedarf nachgetriggert werden kann.

        Keine Ahnung, wie das Threading bei Openhab umgesetzt ist, ob z.B. jede Regel in einem eigenen Thread läuft, sollte dies nicht der Fall sein ist es eher suboptimal den Code für ein paar Sekunden schlafen zu legen.

        Kommentar


          #5
          Jede Rule läuft im eigenen Thread, Rules werden auch mehrfach getriggert, wenn man nicht besondere Vorkehrungen trifft (lock).
          Das else in der Rule hat kein zugehöriges if (das hat ArPa ja schon erwähnt).

          Ich gehe davon aus, dass Du folgendes Verhalten willst:
          1. Bewegung wird registriert -> Licht wird eingeschaltet, Timer wird gestartet
          2. weitere Bewegung innerhalb des Zeitfensters wird registriert -> Licht bleibt eingeschaltet, Timer wird neu gestartet
          3. Timer läuft ab -> Licht wird ausgeschaltet.

          Die bequeme Variante wäre über das expire Binding, aber Du möchtest ja eine variable Ausschaltzeit, das geht nur über einen Timer:

          Code:
          var Timer myTimer = null
          var int iFollowUpSeconds = 15
          
          rule "switch Light"
          when
              Item eg_pre_wohnen_LG1 received command
          then
              if (myTimer != null)
                  myTimer.cancel
              eg_licht_bad_komb.sendCommand(100)
              myTimer = createTimer(now.plusSeconds(iFollowUpSeconds),[
                  eg_licht_bad_komb.sendCommand(0)
                  ]
              )
          end
          Wahlweise könntest Du die Nachlaufzeit über ein Item steuern, also ein Number Item iFollowUpSeconds definieren, dem Du die Zeit z.B. in Sekunden gibst und das Du dann z.B. mit einem Setpoint Widget einstellst. Den Wert bekommst Du innerhalb der Rule mit
          Code:
          (iFollowUpSeconds.state as Number).intValue

          Kommentar


            #6
            Hallo udo1toni,

            wie würdest du denn in der Rule die Abfrage nach der Helligkeit in Lux machen?

            Ich habe nämlich genau das Problem das mein BWM keine helligkeitsabhängige Schaltung kann.

            So schaltet er immer das Licht an.

            Gruß

            Miki

            Kommentar


              #7
              Ah. Ja, da musst Du nur noch ein zusätzliches if-Statement einbauen:
              Code:
              var Timer myTimer = null
              var int iFollowUpSeconds = 15  
              var int iLumenThreshold = 100
              
              rule "switch Light"
              when
                  Item eg_pre_wohnen_LG1 received command
              then
                  if((myLumen.state as Number).intValue < iLumenThreshold) {
                      if (myTimer != null)
                          myTimer.cancel
                      eg_licht_bad_komb.sendCommand(100)
                      myTimer = createTimer(now.plusSeconds(iFollowUpSeconds),[
                          eg_licht_bad_komb.sendCommand(0)
                          ]
                      )
                  }
                  else {
                      if (myTimer != null)
                          myTimer.cancel
                      eg_licht_bad_komb.sendCommand(0)
                  }
              end
              Benötligt wird dann die aktuelle Helligkeit in Lumen auf dem Number Item myLumen. Wenn die Helligkeit sich unterwegs erhöht, wird das Licht ausgeschaltet, allerdings nur, wenn eine Bewegung erkannt wird, sinnvoller wäre dieser Teil dann in einer eigenen Rule untergebracht. Eventuell sollte man dann noch eine Hysterese einbauen, also in einer der beiden Rules noch z.B. 20 Lumen dazu zählen...

              Kommentar


                #8
                Abend zusammen,

                supersupergut! Danke @alle!

                Ich habe mir noch einen Nachtswitch eingebaut, dass Nachts das Licht nur auf 5% geht. Switch ist quasi das WLAN vom Handy, welches wenn es Strom hängt ausgeht.

                PHP-Code:

                rule 
                "isday"

                when
                    Item network_device_x_x_x_x_online changed
                then  
                    
                if (network_device_x_x_x_x_online.state == ON) {      
                        
                IsDay.sendCommand(ON)    
                    } else {
                        
                IsDay.sendCommand(OFF)
                        }
                    }
                end 

                Kommentar


                  #9
                  Followstate geht kürzer (nur der Vollständigkeit halber...):
                  Code:
                  rule "isday"
                  when
                      Item network_device_x_x_x_x_online changed
                  then
                      IsDay.sendCommand(if (network_device_x_x_x_x_online.state == ON) ON else OFF)
                  end

                  Kommentar


                    #10
                    Guten Morgen,

                    entschuldigt bitte meine Zwischenfrage.
                    Da ich auch an meinem openhab 1.8 rumtippe und eigentlich auch alles hinbekomme, auch wenn es mal länger dauert, so denke ich habe ich das eine oder andere wahrscheinlich recht kompliziert programmiert.

                    Wenn ich hier und da immer wieder von der Nutzung von Variablen lese, bin ich beeindruckt, was man damit mit kurzem Code bewerkstelligen kann!

                    Aktuell bastel ich an der Ein- und Ausschaltverzögerung meines "Alarmsystems". Kein echtes, sondern nur das Bewirken von Lichtern und Rollladen bei Reeedkontakt an Fenster und Türen. Ich will halt nach dem aktivieren noch ein paar Sekunden Zeit haben das Haus zu verlassen und umgekehrt.

                    @udo1toni
                    Wo finde ich eine Anleitung, um sich in die Thematik mit der Progarmmierung, speziell das Thema mit Variablen, einlesen zu können, ohne immer wieder hier fragen zu müssen.

                    Gruß
                    Carsten

                    Kommentar


                      #11
                      Dazu kann ich leider wenig beitragen. Die Rules DSL (Domain Specific Language) beruht auf Xtext und XTend. Diese wiederum setzen auf Java auf.
                      Variablen und Konstanten müssen definiert werden, Variablen mit dem Schlüsselwort var, Konstanten mit dem Schlüsselwort val (für Value). Die Reichweite der Definition ist kontextabhängig, außerhalb der Rules -> gültig für alle Rules in diesem File, innerhalb der Rules -> gültig nur innerhalb dieser Rule. Weiterhin gibt es Schlüsselworte für den Typ der Definition, also z.B. int, str, usw. Wenn das Schlüsselwort groß geschrieben wird, z.B. Float, dann ist diese Definition vererbt, klein geschrieben handelt es sich um Primitives. Der Unterschied besteht darin, dass Primitives keine Methoden kennen, z.B. gibt es Float.toString (gibt den Float-Wert als String aus), aber kein int.toString.

                      Es gibt für openHAB so viele Beispielrues, dass man sich daran eigentlich gut orientieren kann.

                      Es gibt Situationen, wo der Einsatz von Variablen unumgänglich ist (z.B. Timer, die kontrollierbar bleiben müssen), oder auch einfach sinnvoll (um z.B. den Code lesbarer zu gestalten), oft braucht es aber keine Variablen, sondern "nur" die geschickte Formulierung im Code.

                      Kommentar


                        #12
                        Napalmrocks , ich hatte gerade ein paar Minuten Zeit... So könnte eine "Verzögerungsregel" aussehen... Erwarte keine 100% Lösung, das ist gerade auf die Schnelle in 10 Minuten entstanden...

                        Code:
                        var Timer externAlarm = null
                        
                        // ============================================================================
                        rule "Alarm scharf stellen"
                        when
                                Bedinungen: z.B. Switch wenn alle das Haus verlassen
                        then
                                logInfo(LogPrefix, "Bedingung für Alarm scharf erfüllt!")
                                if(externAlarm == null)
                                {
                                        logInfo(LogPrefix, "Warte 3 Minute, danach Alarm scharf")
                                        externAlarm = createTimer(now.plusMinutes(3), [|
                                                logInfo(LogPrefix, "3 Minuten sind abgelaufen. Schalte Alarm scharf...")
                                                // Hier alles rein, was nach 3 Minuten verzögert passieren soll
                                                externAlarm = null
                                        ])
                                }
                        end
                        
                        // ============================================================================
                        rule "Alarm unscharf und ggf. scharf schalten abbrechen innerhalb von 3 Minuten"
                        when
                                Bedinungen: z.B. Switch wenn jemand berechtigt das Haus betritt
                        then
                                logInfo(LogPrefix, "Bedingung für Alarm unscharf erfüllt")
                                if(externAlarm != null)
                                {
                                        logInfo(LogPrefix, "3 Minuten Timer läuft noch und wird jetzt abgebrochen...")
                                        externAlarm.cancel()
                                        externAlarm = null
                                }
                        
                                logInfo(LogPrefix, "Berechtigte Person im Haus. Schalte Alarm unscharf...")
                                // Hier alles rein, was für Alarm unscharf passieren soll
                        end
                        Alle sagten: Das geht nicht. Dann kam einer, der wusste das nicht und hat's einfach gemacht.

                        http://cleveres-heim.de

                        Kommentar


                          #13
                          Klasse, vielen Dank, ich werde mir das ansehen und versuchen zu verstehen!

                          Kommentar


                            #14
                            Hello,

                            bin neu bei Openhab und schreib gerade meine zweite Regel. Ich habe versucht meinen Fall an diesen hier anzupassen aber irgendwie schaff ichs nicht.

                            Ich möchte Tageszeitabhängig mit Bewegungsmelder das Licht schalten also ähnlich dem Beispiel hier.

                            Licht einschalten funktioniert ganz gut mit:

                            Code:
                            rule "Licht Gallerie abends AN"
                            when
                            Item FibEye01_Movement changed to ON
                            then
                            if ( (Var_Tageszeit.state == 2) )
                            Dimmer01_Switch.sendCommand(10)
                            if ( (Var_Tageszeit.state == 3) )
                            Dimmer01_Switch.sendCommand(10)
                            Dimmer02_Switch.sendCommand(10)
                            end
                            Licht ausschalten macht Probleme: (vom Prinzip hätte ich es gerne so)

                            Code:
                            //Var_Tageszeit ist ein globales Number Item
                            var Timer myTimer = null
                            var Timer myTimer = 60
                            
                            rule "Licht Gallerie AUS"
                            when
                                Item FibEye01_Movement changed to OFF
                            then
                                if (Var_Tageszeit == 2) 
                                    myTimer = createTimer(now.plusSeconds(iFollowUpSeconds))
                                    check ob FibEye01_Movement == (ON)
                                    wenn ON dann warte erneut xtime
                                    sonst
                                    if (Dimmer01_Switch.state == ON) then Dimmer01_Switch.sendCommand(OFF)
                            
                                if (Var_Tageszeit == 3)
                                    myTimer = createTimer(now.plusSeconds(iFollowUpSeconds))
                                    check ob FibEye01_Movement == (ON)
                                    wenn ON dann warte erneut xtime
                                    sonst
                                    if (Dimmer01_Switch.state == ON) then Dimmer01_Switch.sendCommand(OFF)

                            kann mir bitte wer helfen? Danke!

                            Kommentar


                              #15
                              Du wirfst (wie viele, die neu in die Materie einsteigen) ein paar Dinge durcheinander, und zwar Items und Variablen. Beide halten einen Wert, den man manipulieren kann, oder als Grundlage für Entscheidungen verwenden kann. Aber um an diesen Wert zu kommen, muss man sich verschiedener Mechanismen bedienen.
                              Wert zuweisen Wert auswerten
                              Variable MyVar = 5 if(MyVar == 5)
                              Item MyItem.postUpdate(5) oder
                              MyItem.sendCommand(5)
                              if((MyItem.state as Number) == 5)
                              Es geht also schon beim ersten if() los, wo Du versuchst, ein Item mit einer Zahl zu vergleichen. Du musst aber den Status des Items vergleichen, mehr noch, dieser Status soll als Zahl ausgewertet werden.
                              Gleich in der nächsten Zeile willst Du eine Variable verwenden, die Du aber nicht definiert hast (vermutlich sollte das in der zweiten Zeile der Datei passieren).
                              iFollowUpSeconds muss in dem Kontext zwingend vom Typ Integer oder int sein (also var int iFollowUpSeconds = 60) Sprechende Variablennamen sind toll, sollten aber kurz sein.
                              Die Timer Schreibweise erfordert dann noch eckige Klammern um den Teil, der nach Ablauf des Timers ausgeführt werden soll.

                              Deine Idee hat einen Haken: Wenn sich das Item Var_Tageszeit ändert, während Lichter eingeschaltet sind, wird das Licht eventuell nicht mehr korrekt ausgeschaltet. Es ist also sinnvoller, das Ganze etwas anders anzugehen:
                              Code:
                              var Timer tLight = null
                              
                              val int cTimeout = 60 //val -> eine Konstante, deren Wert zur Laufzeit nicht geändert werden kann
                              
                              rule "Bewegungsmelder"
                              when
                                  Item FibEye01_Movement changed
                              then
                                  if (FibEye01_Movement.state == ON) {
                                      if ((Var_Tageszeit.state as Number) == 2)
                                          Dimmer01_Switch.sendCommand(10)
                                      else if ((Var_Tageszeit.state as Number) == 3) {
                                          Dimmer01_Switch.sendCommand(10)
                                          Dimmer02_Switch.sendCommand(10)
                                      }
                                      if ((Var_Tageszeit.state as Number) == 2 || (Var_Tageszeit.state as Number) == 3) {
                                          if (tLight !== null) tLight.cancel
                                          tLight = createTimer(now.plusSeconds(cTimeout), [
                                              if (FibEye01_Movement.state != ON) {
                                                  Dimmer01_Switch.sendCommand(OFF)
                                                  Dimmer02_Switch.sendCommand(OFF)
                                                  tLight = null
                                              }
                                              else
                                                  tLight.reschedule(now.plusSeconds(cTimeout)
                                          ])
                                      }
                                  }
                                  else
                                      tLight.reschedule(now.plusSeconds(cTimeout)
                              end
                              Der Timer wird also schon gestartet, wenn das Licht eingeschaltet wird. Damit ist sichergestellt, dass das Licht auf jeden Fall ausgeschaltet wird. Solange Bewegung erkannt wird, wird der Timer einfach immer wieder neu gestartet. Wenn keine Bewegung mehr erkannt wird, wird der Timer ebenfalls neu gestartet (damit ist ein Timeout nach der letzten Bewegung sichergestellt).
                              Wenn es keinen ON-Trigger mehr gibt, läuft der Timer zu Ende und schaltet immer beide Lichter aus.

                              Falls der Timer noch läuft, während schon wieder eine neue Bewegung erkannt wird, wird der Timer vorzeitig beendet und neu erstellt.

                              Es gibt übrigens mit dem Expire Binding eine sehr gute Möglichkeit, das einfacher zu gestalten. es wird ein default Wert definiert, in den das Item nach einer festgelegten Zeit übergeht, es sei denn, es erfolgt ein Trigger auf einen anderen Wert. Dabei kann man auch angeben, ob nun ein postUpdate oder ein sendCommand ausgeführt werden soll. Das einzige, was das Bindng gegenüber dem Rule-Timer nicht bietet, ist, den Timeout dynamisch anzupassen.

                              Kommentar

                              Lädt...
                              X