Ankündigung

Einklappen
Keine Ankündigung bisher.

Zeit zwischen Aus und Ein ermitteln

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

    Zeit zwischen Aus und Ein ermitteln

    Hallo,

    Ich möchte die Zeit zwischen zwischen dem Ausschalten und dem Wiedereinschalten ermitteln.

    Dazu habe ich folgende Rule:

    Code:
    rule "Zeit Licht Diele"
    when
        Item EG_Diele_Licht changed
    then
        tLichtDiele = (DateTimeType.valueOf(tLichtDiele_LastUpdateOFF) - DateTimeType.valueOf(tLichtDiele_LastUpdateON))
    
        if (EG_Diele_Licht.state == ON)
            tLichtDiele_LastUpdateON.postUpdate (new DateTimeType().toString)
    
        if (EG_Diele_Licht.state == OFF)
         tLichtDiele_LastUpdateOFF.postUpdate (new DateTimeType().toString)
    
    end
    Aber wie kann ich hier die Differenz der beiden Zeiten ermitteln?

    Das hier funktioniert so nicht.
    Code:
    tLichtDiele = (DateTimeType.valueOf(tLichtDiele_LastUpdateOFF) - DateTimeType.valueOf(tLichtDiele_LastUpdateON))
    2020-06-17 20:35:42.513 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Zeit Licht Diele': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.core.library.types.DateTimeT ype.valueOf(java.lang.String) on instance: null

    #2
    Also, tLichtDiele_LastUpdateOFF und tLichtDiele_LastUpdateON sind vom Typ DateTime? Es sind Items? Dann musst Du auch den Status des Items verwenden, also tLichtDiele_LastUpdateON.state. Gewöhnlich wird die Berechnung so aussehen:
    Code:
    tLichtDiele = (tLichtDiele_LastUpdateOFF.state as DateTimeType) - (tLichtDiele_LastUpdateON.state as DateTimeType)
    Wobei ich mir nicht sicher bin, ob da das korrekte Ergebnis raus kommt. Wenn Du das Item persistierst, kannst Du Dir den letzten Ausschaltzeitpunkt beim Einschalten aus der Persistence ausgeben lassen und als Berechnungsgrundlage verwenden. Oder Du verwendest globale Variablen dazu:
    Code:
    var Long lLightOffTime = null
    
    rule "Zeit Licht Diele"
    when
        Item EG_Diele_Licht changed
    then
        var Number nDuration = 0
        if(newState == ON) {
            if(lLightOffTime !== null)
                nDuration = now.millis - lLightOffTime
                logInfo("timeLight","Licht Diele war {} Sekunden aus",(nDuration/1000).intValue)
        } else {
            lLightOffTime = now.millis
        }
    end
    Falls das Licht aus geht, wird die Startzeit (now.Millis) in der globalen Variablen lLightOffTime gespeichert.
    Falls das Licht an geht, wird geprüft, ob lLightOffTime !== null ist (dann sollte es eine gültige Zahl enthalten), ist das der Fall, wird diese Zahl von now.Millis abgezogen und das Ergebnis ausgegeben. (das !== bedeutet nicht identisch und ist in diesem Fall so notwendig.)

    Kommentar


      #3
      Zitat von udo1toni Beitrag anzeigen
      Gewöhnlich wird die Berechnung so aussehen:
      Code:
      tLichtDiele = (tLichtDiele_LastUpdateOFF.state as DateTimeType) - (tLichtDiele_LastUpdateON.state as DateTimeType)
      Das hat leider nicht geklappt, VSC hat das - angemeckert.

      Zitat von udo1toni Beitrag anzeigen
      Oder Du verwendest globale Variablen dazu:
      Code:
      var Long lLightOffTime = null
      
      rule "Zeit Licht Diele"
      when
      Item EG_Diele_Licht changed
      then
      var Number nDuration = 0
      if(newState == ON) {
      if(lLightOffTime !== null)
      nDuration = now.millis - lLightOffTime
      logInfo("timeLight","Licht Diele war {} Sekunden aus",(nDuration/1000).intValue)
      } else {
      lLightOffTime = now.millis
      }
      end
      Damit klappt es. Danke!

      Jetzt möchte ich noch gerne zählen wie oft die Zeit kleiner, größer einens bestimmten Werts war.
      Doch leider erhalte ich immer den folgenden Fehler:

      Rule 'Zeit Licht Diele': Could not cast NULL to java.lang.Number; line 37, column 32, length 19
      Der Teil meiner Ruls sieht wie folgt aus:

      Code:
      if(lLightOffTime !== null){            
                  nDuration = now.millis - lLightOffTime
                  logInfo("timeLight","Licht Diele war {} Sekunden aus",(nDuration/1000).intValue)
                  nLichtDiele.postUpdate(nDuration/1000)
              }
                
       if (nLichtDiele.state < 30){
                      if (n30 === null)
                      {
                          n30.postUpdate(0)
                      }
                      n30.postUpdate(n30.state as Number + 1)
                  }
      Was ist denn hier falsch?

      Kommentar


        #4
        n30 ist ein Item? Das oben gesagte gilt ausnahmslos für alle Items. den Status bekommst Du ausschließlich über .state
        Und dann kommt noch etwas erschwerend hinzu: openHAB arbeitet asynchron. Wenn Du nLichtDiele.postUpdate(wert) ausführst und unmittelbar anschließend if(nLichtDiele.state < 30) abfragst, wird mit sehr hoher Wahrscheinlichkeit ein alter Wert geliefert.
        Die Prüfung auf === null ist im Übrigen auch falsch. Ein Item kann als Status NULL haben, aber nicht null. Ein Vergleich auf identisch (===) ist dabei nicht möglich (es werden dabei Zeiger verglichen, das geht nur bei Variablen oder Konstanten).

        Kommentar


          #5
          Zitat von udo1toni Beitrag anzeigen
          n30 ist ein Item?
          Ja, ist ein Item vom Typ Number.

          Zitat von udo1toni Beitrag anzeigen
          Und dann kommt noch etwas erschwerend hinzu: openHAB arbeitet asynchron. Wenn Du nLichtDiele.postUpdate(wert) ausführst und unmittelbar anschließend if(nLichtDiele.state < 30) abfragst, wird mit sehr hoher Wahrscheinlichkeit ein alter Wert geliefert.
          Die Prüfung auf === null ist im Übrigen auch falsch. Ein Item kann als Status NULL haben, aber nicht null. Ein Vergleich auf identisch (===) ist dabei nicht möglich (es werden dabei Zeiger verglichen, das geht nur bei Variablen oder Konstanten).
          Ok, dann lass ich die Abfrage auf null weg und Setze das Zählen in eine eigene Rule?
          So dann richtig?

          Code:
          var Long lLightOffTime = null
          
          rule "Zeit Licht Diele"
          when
              Item EG_Diele_Licht changed
          then
              var Number nDuration = 0
              if(newState == ON) {
                  if(lLightOffTime !== null){            
                      nDuration = now.millis - lLightOffTime
                      logInfo("timeLight","Licht Diele war {} Sekunden aus",(nDuration/1000).intValue)
                      nLichtDiele.postUpdate(nDuration/1000)
                  }
               } else {
                  lLightOffTime = now.millis
              }
          end
          
          rule "Zaehlen Licht Diele"
          when
              Item nLichtDiele changed
          then
                      if (nLichtDiele.state < 30)
                      {
                          n30.postUpdate(n30.state as Number + 1)
                      }
          end

          Kommentar


            #6
            Das Zählen kannst Du schon in der ersten Rule mit erledigen. Nur die Prüfung auf null geht so nicht.Stattdessen musst Du die Prüfung anders erledigen:
            Code:
            var Long lLightOffTime = null
            
            rule "Zeit Licht Diele"
            when
                Item EG_Diele_Licht changed
            then
                var Number nDuration = 0
                var Number nLightCount = 0
                if(newState == ON) {
                    if(lLightOffTime !== null){            
                        nDuration = now.millis - lLightOffTime
                        logInfo("timeLight","Licht Diele war {} Sekunden aus",(nDuration/1000).intValue)
                        nLichtDiele.postUpdate(nDuration/1000)
                        if(n30.state instanceof Number)
                            nLightCount = n30.state as Number
                        if((nDuration/1000).intValue < 30)
                            n30.postUpdate(nLightCount + 1)
                    }
                 } else {
                    lLightOffTime = now.millis
                }
            end
            Die Prüfung if(n30.state instanceof Number) stellt sicher, dass der Wert nur dann aus dem Item ausgelesen wird, wenn er vom Typ Number ist. Ist das nicht der Fall, so wird der Wert auf 0 belassen, was dann ja passen sollte. Anschließend wird nicht der Wert aus dem Item verwendet, sondern direkt der berechnete Wert (der steht ja zur Verfügung).
            Zuletzt geändert von udo1toni; 24.06.2020, 23:40.

            Kommentar


              #7
              Danke!
              Funktioniert einwandfrei.

              Kommentar

              Lädt...
              X