Ankündigung

Einklappen
Keine Ankündigung bisher.

String in Rule vergleichen

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

    String in Rule vergleichen

    Hallo zusammen,

    ich habe mir folgende Rule gebaut, damit mein Mähroboter bei Regen in die Garage fährt. Ich vermute er komm mit dem State und dem Vergleichen von z.B. ok_cutting_timer_overriden nicht klar oder was meint ihr? Muss ich das anders bauen?


    Code:
    rule "Rasenmäherroboter Regen Ladestation verbleiben"
    when
        Item ws_regen changed to OPEN
    then
        if (au_rmr_regenschutz.state==ON){
        if (au_rmr_status.state==parked_timer) {    
    
        au_rmr_parken_pausieren.sendCommand(ON)
        sendBroadcastNotification("Da es regnet, wurde der geparkte Rasenmäherroboter auf Pause gesetzt.")
        Thread::sleep(1800000)
        if (ws_regen.state==OPEN){
        Thread::sleep(1800000)
        }
        else{
        au_rmr_zeitplan_fortsetzen.sendCommand(ON)
        }
        if (ws_regen.state==OPEN){
        Thread::sleep(1800000)
        }
        else{
        au_rmr_zeitplan_fortsetzen.sendCommand(ON)
        }
        if (ws_regen.state==OPEN){
        Thread::sleep(1800000)
        }
        else{
        au_rmr_zeitplan_fortsetzen.sendCommand(ON)
        }
    
        }
        }
    end

    #2
    Ogottogott... Bitte niemals Thread::sleep() mit Werten größer 500 nutzen.

    Was ich auch nicht verstehe, ist Dein Thread Titel. Nirgendwo ein String Vergleich...

    Na ja, eventuell doch, das hier
    Code:
    if (au_rmr_status.state==parked_timer)
    könnte ein String Vergleich sein. Falls parked_timer eine Variable ist, die einen String enthält. Wenn parked_timer der String sein soll, müsste er in Anführungszeichen stehen.
    Ansonsten verstehe ich Deine Regel nicht. Ich erinnere mich an einen anderen Thread (jepp... gerade gefunden...) in dem es darum ging, dass der Regen seit drei Stunden geendet hat.

    Ich gehe jetzt mal davon aus, dass ws_regen.state == OPEN bedeutet, dass es nicht mehr regnet? Eine einfache Variante wäre, ein Item zu definieren, welches den Rasenmäher freigibt oder auch nicht. Das Item wechselt also auf ON, wenn es drei Stunden nicht geregnet hat. Es wechselt auf OFF, wenn es beginnt zu regnen. Sieht so aus:
    Code:
    // Globale Variablen immer zu Beginn der Datei definieren!
    var Timer tMower = null
    
    rule "set mower_enable"
    when
        Item ws_regen changed
    then
        tMower?.cancel
        if(ws_regen.state == OPEN)
            tMower = createTimer(now.plusHours(3), [|
                mower_enable.postUpdate(ON)
            ])
        else
            mower_enable.postUpdate(OFF)
    end
    Wenn sich der Zustand von ws_regen ändert, triggert die Rule. Falls es regnet, wird ein eventuell laufender Timer unterbrochen und mower_enable auf OFF gesetzt. Falls es nicht (mehr) regnet, wird ein eventuell laufender Timer ebenfalls abgebrochen, anschließend wird der Timer angelegt, der drei Stunden später mower_enable auf ON setzt.

    Du kannst jetzt eine zweite Rule bauen, die mittels mower_enable die Pause erzwingt oder beendet, diese Rule ist einfach.

    Im Unterschied zu Thread::sleep() läuft die Rule nur extrem kurz (wenige Millisekunden). Deine Rule läuft zwei Stunden am Stück und tut: nichts. Dabei hast Du keine Vorkehrungen getroffen, dass die Rule vielleicht mehrfach ausgelöst wird.
    Stell Dir vor, es kommen immer wieder mal kurze Regenschauer. ws_regen kippt immer wieder zwischen OPEN und CLOSED hin und her, und zwar vielleicht in der Größenordnung 5 Minuten pro Kippen.Nach 60 Minuten wurde die Rule 6 mal getriggert. Leider läuft die Rule aber beim 6. Mal nicht mehr los, und auch keine andere Rule, weil alle 5 Threads, die openHAB zur Verfügung stellt, um Rules laufen zu lassen, beschäftigt sind. Mit Nichts tun. Es geht dabei nicht darum, dass viel Rechenzeit vergeudet würde, trotzdem laufen keine weiteren Rules mehr...
    Zuletzt geändert von udo1toni; 21.08.2019, 19:30.

    Kommentar


      #3
      Hallo zusammen,

      also wenn ws_regen OPEN ist dann hat der Regen eingesetzt.

      Das Item
      au_rmr_status kann verschiedene Stati annehmen: Darunter z.B.
      parked_timer Das bedeutet, dass das Status Item des Mähroboters den Status parked_timer bekommen hat. Auf diese Stati möchte ich prüfen. Was mache ich in meine Rule dann falsch?

      Kommentar


        #4
        Zitat von SaschaQ Beitrag anzeigen
        Was mache ich in meine Rule dann falsch?
        Mal abgesehen davon, einen weiteren Threat für's gleiche Thema? OK dies hat nichts mit der rule zu tun.

        Zum einen hat Dir UdoToni ja schon ein paar Hinweise gegeben, dies solltest Du mal testen.
        Kleiner Tipp von mir: UdoToni hat ein sehr gutes Händchen für smarte Rules
        Speziell der Tipp zum Thema sleep vs. Timer, was Resourcen beim rechnen schont und sicher stellt, dass überhaupt rules laufen.

        Wenn "parkedTimer" der Wert ist, mus dies in Anführungszeichen stehen. Aber dies wurde ja auch schon erwähnt.
        Daher solltest Du nun die Tipps einmal austesten und dann weiterschauen

        Es macht also nicht Deine Rule etwas falsch

        Darüber hinaus fehlen noch weitere Informationen zu den Things, die bei einem Gardena Roboter angelegt werden und welche Werte diese haben können.
        Hat ja nicht jeder einen Gardena Bei meinem Worx kann ich - neben dem eingabauten Timer über den Regensensor des Roboters - die Mähzeit auf -100% setzen um den manuell zu parken.

        Kommentar


          #5
          Zitat von SaschaQ Beitrag anzeigen
          Hallo zusammen,

          also wenn ws_regen OPEN ist dann hat der Regen eingesetzt.

          Das Item
          au_rmr_status kann verschiedene Stati annehmen: Darunter z.B.
          parked_timer Das bedeutet, dass das Status Item des Mähroboters den Status parked_timer bekommen hat. Auf diese Stati möchte ich prüfen. Was mache ich in meine Rule dann falsch?
          Ah. Dann muss die Logik natürlich umgedreht sein. Wenn es beginnt zu regnen, setzt Du mower_enable auf OFF, wenn es aufhört (ws_regen wechselt nach CLOSED) startet der Timer, der mower_enable wieder auf ON setzt.

          Die passende Rule, um den Roboter dann zu steuern, kann damit den Rest erledigen.
          Code:
          rule "Rasenmäherroboter"
          when
              Item mower_enable changed
          then
              if(mower_enable.state == ON) {
                  if(au_rmr_status.state.toString == "parked_timer") {                // vermutlich kann man auf das .toString auch verzichten
                      sendBroadcastNotification("Der Rasenmäher kann weiter mähen!")
                      au_rmr_zeitplan_fortsetzen.sendCommand(ON)
              } else {
                  if(au_rmr_status.state.toString == "mowing") {                // oder was auch immer...
                      sendBroadcastNotification("Da es regnet, wurde der geparkte Rasenmäherroboter auf Pause gesetzt.")
                      au_rmr_parken_pausieren.sendCommand(ON)
                  }
              }
          end
          Natürlich kannst Du alle anderen möglichen Status ebenso abfeiern.
          Zuletzt geändert von udo1toni; 18.08.2019, 19:19.

          Kommentar


            #6
            Hallo zusammen,

            zunächst vielen Dank für Euren Input, das ist wirklich klasse.

            Ich habe jetzt folgendes in Anlehnung an Udo1Tonis Vorschlag gemacht:

            Wie schon erwähnt ist der Status von ws_regen=Closed (Regen aus) und OPEN (Regen an). Ich habe damit die Timer Rule nur gedreht.

            Mein Mähroboter hat folgende Stati:
            parked_park_selected=Parken und Pausieren
            parked_timer= Parken bis zum nächsten Zeitplan
            ok_cutting=Mähen nach Zeitplan
            ok_cutting_timer_overridden=Manuelles Mähen ohne Zeitplan
            ok_leaving= Verlasse Ladestation

            Wenn der Mäher auf enabled gesetzt wird und ist im Status parked_park_selected dann wird er auf parked_timer gesetzt.
            Wenn der Mäher auf enabled gesetzt wird, dann mäht der Roboter wenn er im Status ok_leaving oder ok_cutting_timer_overridden oder ok_cutting oder parked_timer ist einfach weiter oder setzt den Zeitplan fort.

            Wenn der Mäher auf disabled gesetzt wird dann wird bei den Stati parked_timer,ok_cutting,ok_cutting_timer_overridde n oder ok_leaving der Status auf parked_park_selected gesetzt.

            Desweiteren habe ich noch das Item Regenschutz drumherum gebaut, damit ich den Regenschutz quasi abschalten kann.

            Könnt ihr mal checken ob das so passt?



            Code:
            rule "Rasenmäherroboter Regenschutz Timer"
            when
                ws_regen changed
            then
                tMower?.cancel
                if(ws_regen.state == CLOSED)
                    tMower = createTimer(now.plusHours(3), [|
                        mower_enable.postUpdate(ON)
                    ])
                else
                    mower_enable.postUpdate(OFF)
            end
            Code:
            rule "Rasenmäherroboter Regenschutz"
            when
                Item mower_enable changed
            then
               if (au_rmr_regenschutz.state==ON){
               if(mower_enable.state == ON) {
                    if(au_rmr_status.state.toString == "parked_park_selected") {            
                        sendBroadcastNotification("Der Rasenmäherzeitplan wird fortgesetzt, da es nicht mehr regnet!")
                        au_rmr_zeitplan_fortsetzen.sendCommand(ON)
                }
                
                if ((au_rmr_status.state=="ok_cutting") || (au_rmr_status.state=="ok_cutting_timer_overridden") || (au_rmr_status.state=="ok_leaving") || (au_rmr_status.state=="parked_timer"))  {
                sendBroadcastNotification("Der Rasenmäher mäht weiter oder setzt den Zeitplan fort, da es nicht mehr regnet!")
                
            }
            else {    
            
                    if ((au_rmr_status.state=="ok_cutting") || (au_rmr_status.state=="ok_cutting_timer_overridden") || (au_rmr_status.state=="ok_leaving") || (au_rmr_status.state=="parked_timer"))  {
                    sendBroadcastNotification("Da es regnet, wurde der geparkte Rasenmäherroboter auf Parken und Pausieren gesetzt.")
                    au_rmr_parken_pausieren.sendCommand(ON)
            }
             
                }
                }
                }
            end


            Kommentar


              #7
              Jetzt habe ich gesehen dass ich die folgenden Fehler drin habe:

              2019-08-21 15:22:05.797 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'Roboter.rules' has errors, therefore ignoring it: [161,1]: no viable alternative at input ' '
              [161,182]: no viable alternative at input ' '
              [163,1]: mismatched input ' ' expecting '}'
              [175,2]: extraneous input '}' expecting 'end'

              finde die fehler aber irgendwie nicht.


              Kommentar


                #8
                Da müsste man nun die Zeilennummern haben (das ist die erste Zahl). Ic hschau heut abend mal, ob ich den Fehler auch so finde (ist bestimmt nur irgendwo eine Klammer oder sowas)

                Kommentar


                  #9
                  Der erste Fehler ist in der Rule "Rasenmäherroboter Regenschutz Timer", dort fehlt das Schlüsselwort Item vor dem Item (den Fehler hatte ich selbst in meiner Rule oben drin, sorry.)
                  Die zweite Rule stimmt aber so auch nicht, mindestens ist da was mit den Ebenen durcheinander geraten. Ich denke, so sollte es korrekt sein:
                  Code:
                  rule "Rasenmäherroboter Regenschutz Timer"
                  when
                      Item ws_regen changed
                  then
                      tMower?.cancel
                      if(ws_regen.state == CLOSED)
                          tMower = createTimer(now.plusHours(3), [|
                              mower_enable.postUpdate(ON)
                          ])
                      else
                          mower_enable.postUpdate(OFF)
                  end
                  
                  rule "Rasenmäherroboter Regenschutz"
                  when
                      Item mower_enable changed
                  then
                     val boolean bOk = au_rmr_status.state=="ok_cutting" || au_rmr_status.state=="ok_cutting_timer_overridden" || au_rmr_status.state=="ok_leaving" || au_rmr_status.state=="parked_timer"
                     if (au_rmr_regenschutz.state==ON){
                         if(mower_enable.state == ON && au_rmr_status.state.toString == "parked_park_selected") {            
                             sendBroadcastNotification("Der Rasenmäherzeitplan wird fortgesetzt, da es nicht mehr regnet!")
                             au_rmr_zeitplan_fortsetzen.sendCommand(ON)
                         }
                         if(mower_enable.state == ON && bOk)
                             sendBroadcastNotification("Der Rasenmäher mäht weiter oder setzt den Zeitplan fort, da es nicht mehr regnet!")
                         if(mower_enable.state == OFF && bOk) {
                             sendBroadcastNotification("Da es regnet, wurde der geparkte Rasenmäherroboter auf Parken und Pausieren gesetzt.")
                             au_rmr_parken_pausieren.sendCommand(ON)
                         }
                      }
                  end
                  Eventuell könnte man eine Zeile auch noch optimieren:
                  Code:
                  val boolean bOk = ("ok_cutting_timer_overridden ok_leaving parked_timer").contains(au_rmr_status.state.toString)
                  Ich bin mir allerdings nicht sicher, ob das tatsächlich funktioniert. In der Theorie prüft die Methode .contains(), ob der String enthalten ist. Da ok_cutting auch im String ok_cutting_timer_overridden enthalten ist, kann man sich diesen String sogar sparen. Sicher funktioniert die Variante über ein Array, man erzeugt ein Array mit allen gültigen Status (Stati ist falsch ) und kann dann prüfen, ob der aktuelle Status in diesem Array enthalten ist. Aber mit einem String sollte es genauso funktionieren. Voraussetzung ist natürlich, dass das Item nicht noch weitere Teilstrings enthalten kann.
                  Die Konstante setze ich hier nur ein, um den Code etwas zu vereinfachen, deshalb auch die && Verknüpfung, statt einer weiteren if-Ebene. Ich bezweifele, dass die 2. Meldung (enable ON && bOk) jemals erscheint, denn der Status hat ja gewechselt, also von OFF nach ON, damit muss der Mäher noch im Pause Modus sein (bis das sendCommand aus der vorigen Bedingung wirkt (Status geändert), ist die Rule längst abgearbeitet).

                  Kommentar


                    #10
                    Super vielen Dank, ich werde es testen

                    Kommentar


                      #11
                      Hallo zusammen,

                      ich muss mich nochmal an Euch wenden:

                      Leider wird mein Mähroboter bei Regen nicht auf Pause gesetzt mit den folgenden Rules:

                      @ Udo1Toni

                      weist du warum?

                      Code:
                      var Timer tMower = null
                      
                      rule "Rasenmäherroboter Regenschutz Timer"
                      when
                          Item ws_regen changed
                      then
                          tMower?.cancel
                          if(ws_regen.state == CLOSED)
                              tMower = createTimer(now.plusHours(3), [|
                                  mower_enable.postUpdate(ON)
                              ])
                          else
                              mower_enable.postUpdate(OFF)
                      end
                      
                      rule "Rasenmäherroboter Regenschutz"
                      when
                          Item mower_enable changed
                      then
                         val boolean bOk = au_rmr_status.state=="ok_cutting" || au_rmr_status.state=="ok_cutting_timer_overridden" || au_rmr_status.state=="ok_leaving" || au_rmr_status.state=="parked_timer"
                         if (au_rmr_regenschutz.state==ON){
                             if(mower_enable.state == ON && au_rmr_status.state.toString == "parked_park_selected") {            
                                 sendBroadcastNotification("Der Rasenmäherzeitplan wird fortgesetzt, da es nicht mehr regnet!")
                                 au_rmr_zeitplan_fortsetzen.sendCommand(ON)
                             }
                             if(mower_enable.state == ON && bOk)
                                 sendBroadcastNotification("Der Rasenmäher mäht weiter oder setzt den Zeitplan fort, da es nicht mehr regnet!")
                             if(mower_enable.state == OFF && bOk) {
                                 sendBroadcastNotification("Da es regnet, wurde der geparkte Rasenmäherroboter auf Parken und Pausieren gesetzt.")
                                 au_rmr_parken_pausieren.sendCommand(ON)
                             }
                          }
                      end

                      Kommentar


                        #12
                        Wäre halt die Frage, an welches Stelle etwas schief geht. Dafür solltest Du ein paar log Meldungen einbauen.

                        Kommentar


                          #13
                          Hallo Udo 1 Toni,

                          ich habe jetzt mal über das KNX auf die GA für den Regen eine 1 gesendet um zu schauen ob irgendwas passiert. Aber irgendwie springt er garnicht in die Rule rein.

                          Kann es sein, dass irgendwas Syntax mäßiges noch nicht passt?


                          Code:
                          rule "Rasenmäherroboter Regenschutz Timer"
                          when
                              Item ws_regen changed
                          then
                              tMower?.cancel
                              if(ws_regen.state == CLOSED)
                                  tMower = createTimer(now.plusHours(3), [|
                                      mower_enable.postUpdate(ON)
                                  ])
                              else
                                  mower_enable.postUpdate(OFF)
                          end
                          
                          rule "Rasenmäherroboter Regenschutz"
                          when
                              Item mower_enable changed
                          then
                             val boolean bOk = au_rmr_status.state=="ok_cutting" || au_rmr_status.state=="ok_cutting_timer_overridden" || au_rmr_status.state=="ok_leaving" || au_rmr_status.state=="parked_timer"
                             if (au_rmr_regenschutz.state==ON){
                                 if(mower_enable.state == ON && au_rmr_status.state.toString == "parked_park_selected") {            
                                     sendBroadcastNotification("Der Rasenmäherzeitplan wird fortgesetzt, da es nicht mehr regnet!")
                                     au_rmr_zeitplan_fortsetzen.sendCommand(ON)
                                 }
                                 if(mower_enable.state == ON && bOk)
                                     sendBroadcastNotification("Der Rasenmäher mäht weiter oder setzt den Zeitplan fort, da es nicht mehr regnet!")
                                 if(mower_enable.state == OFF && bOk) {
                                     sendBroadcastNotification("Da es regnet, wurde der geparkte Rasenmäherroboter auf Parken und Pausieren gesetzt.")
                                     au_rmr_parken_pausieren.sendCommand(ON)
                                 }
                              }
                          end
                          Nachtrag:

                          Ich habe jetzt die Rule für den mower_enable wie folgt geändert:
                          Code:
                          rule "Rasenmäherroboter Regenschutz Timer"
                          when
                              Item ws_regen changed
                          then
                              tMower?.cancel
                              if(ws_regen.state == CLOSED)
                                  tMower = createTimer(now.plusHours(3), [|
                                      mower_enable.sendCommand(ON)
                                  ])
                              else
                                  mower_enable.sendCommand(OFF)
                          end

                          Nun wird beim Regen auch das mower enagle On oder Off gesetzt.

                          Aber die Rule für den Status wird nicht getriggert. Liegt es vielleicht am val boolean bOK ? Das hatten wir vorher nicht.
                          Zuletzt geändert von SaschaQ; 28.09.2019, 11:25.

                          Kommentar


                            #14
                            Nein, das nicht an dem Primitive, sondern am falschen Trigger für die Rule. changed reagiert auf Statusänderungen (die durch postUpdate ausgelöst werden können). Wenn Du stattdessen per sendCommand einen Befehl sendest, muss die Rule halt auf received command triggern.

                            Kommentar


                              #15
                              Es scheint jetzt zu funktionieren. Ich habe jetzt nur in der Timer Rule von postUpdate auf sendCommand geändert. Denke das spielt ja keine Rolle oder?


                              Zur Erklärung: Wenn es Regnet wird der Roboter auf Disabled gesetzt. Setzt der Regen aus, wird ein Timer aktiviert, der 3 Stunden runterzählt. Wird während des laufenden Timers wieder auf Regen gewechselt wird der Roboter wieder auf Disabled gesetzt und der Timer abgebrochen. Läuft der Timer komplett runter ohne Regen wird der Roboter wieder auf Enabled gesetzt. RIchtig=

                              Kommentar

                              Lädt...
                              X