Ankündigung

Einklappen
Keine Ankündigung bisher.

Stromverbrauch bzw. Laufzeit der Lampen mitschreiben

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

    #16
    Warum macht ihr das mit einer Regel die alle Sekunde aufgerufen wird? Hat das einen Vorteil?

    Ne Regel die beim Einschalten den Zeitstempel nimmt und beim Ausschalten wieder. Die Differenz ist die Zeit die die Lampe eingeschaltet war. Die Differenz wird beim Ausschalten in einen Summenzähler addiert.

    Spart Last auf OH und spart damit Strom ,-).

    Kommentar


      #17
      Zitat von RaK Beitrag anzeigen
      Warum macht ihr das mit einer Regel die alle Sekunde aufgerufen wird? Hat das einen Vorteil?

      Ne Regel die beim Einschalten den Zeitstempel nimmt und beim Ausschalten wieder. Die Differenz ist die Zeit die die Lampe eingeschaltet war. Die Differenz wird beim Ausschalten in einen Summenzähler addiert.

      Spart Last auf OH und spart damit Strom ,-).
      Hallo RaK,

      keine Frage deine Einwände sind alle berechtigt. Die Regel muss nicht zwingend alle Sekunde aufgerufen werden, es würde auch genüge diese jede Minute aufzurufen. --> Reduzierung der Systemlast.

      Jan0815 und Ich sind keine Programmierer. Ich habe den für mich "einfachsten Weg" gewählt., mit einfachen Zahlen und String kann ich umgehen.

      Vorteil meiner Lösung ist, dass ich Sekunden/Minutengenau den aktuellen Status habe wenn z.B. Ein Lampe mehrere Stunden an ist. Bei deiner Lösung wird erst beim Ausschalten aktualisiert.

      Bitte nicht Falsch verstehen, ich möchte dein Lösungsvorschlag nicht schlecht machen, im Gegenteil ich finde ihn interessant da ich auf einem Raspberry arbeite und Ressourcen schonend arbeiten muss.

      Kannst du uns zeigen wie das mit den zeitstempeln funktioniert?

      Jede Hilfe und Code-Beispiele sind jederzeit Herzlich willkommen!

      Danke!

      Gruß
      mepi

      Kommentar


        #18
        Ne Regel die beim Einschalten den Zeitstempel nimmt und beim Ausschalten wieder. Die Differenz ist die Zeit die die Lampe eingeschaltet war. Die Differenz wird beim Ausschalten in einen Summenzähler addiert.
        Das hab ich jetzt mal in einer ersten Version umgesetzt, ist aber ganz sicher noch deutlich verbesserungswürdig. Hier mal exemplarisch für eine Steckdose:

        Items:
        Code:
        Number Steckdosen_Wohnen_Heizung_links_Zaehler "Steckdose Heizung li. [%d]"    (gOperatingHours)  
        String Steckdosen_Wohnen_Heizung_links_Betriebsstunden "Steckdose Heizung li. [%s]"    (gOperatingHoursFormated)
        Die beiden Gruppen nutze ich vor allem um mir die Einträge in der db4o.persist zu vereinfachen.

        Dazu eine Regel, die beim Ausschalten die Zeitdifferenz zum Zähler addiert:

        Code:
        import org.openhab.core.library.types.*
        import java.util.Calendar
        import java.util.Date
        import java.util.TimeZone
        
        var Calendar Steckdosen_Wohnen_Heizung_links_OnTime
        
        rule "Aktualisiere Betriebsstunden Steckdosen_Wohnen_Heizung_links_Schalten"
        when
            Item Steckdosen_Wohnen_Heizung_links_Schalten changed
        then
            if (Steckdosen_Wohnen_Heizung_links_Schalten.state == ON) {
                Steckdosen_Wohnen_Heizung_links_OnTime = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin"))  
            } else if (Steckdosen_Wohnen_Heizung_links_Schalten.state == OFF) {
                var Calendar now   = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin")) 
                var Number Diff    =  (now.getTimeInMillis() - Steckdosen_Wohnen_Heizung_links_OnTime.getTimeInMillis()) / 1000
                var Number Zaehler = (Steckdosen_Wohnen_Heizung_links_Zaehler.state as DecimalType) + Diff
                Steckdosen_Wohnen_Heizung_links_Zaehler.postUpdate(Zaehler)
                
                var Number h = (Zaehler/3600).intValue
                var Number m = ((Zaehler-h*3600)/60).intValue
                var Number s = ((Zaehler-h*3600 - m*60)).intValue
                var String TimeString = h + ":" 
                if (m < 10) {TimeString = TimeString + "0" + m.toString + ":"} else {TimeString = TimeString + m.toString + ":"}
                if (s < 10) {TimeString = TimeString + "0" + s.toString      } else {TimeString = TimeString + s.toString      } 
               	
                Steckdosen_Wohnen_Heizung_links_Betriebsstunden.postUpdate(TimeString)
        		
                logInfo("operating hours rules", "Updated operating counter for Steckdosen_Wohnen_Heizung_links_Schalten: " + Zaehler)
            }
        end

        Initialisierung beim Start:
        Code:
        rule "Initialisiere Betriebsstundenzaehler"
        when
            System started
        then
            Steckdosen_Wohnen_Heizung_links_OnTime = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin"))   
            
            if (Steckdosen_Wohnen_Heizung_links_Zaehler.state == Uninitialized) {
                Steckdosen_Wohnen_Heizung_links_Zaehler.postUpdate(0)
            }
        end
        Zusätzlich kann man bei lang laufenden Verbrauchern den Zähler auch periodisch, dann aber mit langem Intervall aktualisieren:

        Code:
        rule Betriebsstundenzaehler
        when
          Time cron "* 0/30 * * * ?" // Abfrage alle 30min 
        then
            var Number Diff
            var Number Zaehler
            var Calendar now   = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin")) 
        
            if (Steckdosen_Wohnen_Heizung_links_Schalten.state == ON) {
                Diff    =  (now.getTimeInMillis() - Steckdosen_Wohnen_Heizung_links_OnTime.getTimeInMillis()) / 1000
                Zaehler = (Steckdosen_Wohnen_Heizung_links_Zaehler.state as DecimalType) + Diff
                Steckdosen_Wohnen_Heizung_links_Zaehler.postUpdate(Zaehler)
                Steckdosen_Wohnen_Heizung_links_OnTime = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin"))  
                
                var Number h = (Zaehler/3600).intValue
                var Number m = ((Zaehler-h*3600)/60).intValue
                var Number s = ((Zaehler-h*3600 - m*60)).intValue
                var String TimeString = h + ":" 
                if (m < 10) {TimeString = TimeString + "0" + m.toString + ":"} else {TimeString = TimeString + m.toString + ":"}
                if (s < 10) {TimeString = TimeString + "0" + s.toString      } else {TimeString = TimeString + s.toString      } 
               	
               Steckdosen_Wohnen_Heizung_links_Betriebsstunden.postUpdate(TimeString)
            }
        end
        Ich bin noch beim Testen, Fehler sind also durchaus noch wahrscheinlich.

        Natürlich ist das eine Sache bei der man sich, gerade bei vielen Verbrauchern, Funktionen in den Regeln wünscht...

        Was mir überhaupt nicht gefällt ist die umständliche Formatierung des Strings zur Anzeige, eigentlich sogar schon nicht die Tatsache zwei Items zu benötigen. Wenn ich es richtig sehe, kennt das String Item aber keinen Format Operator mit dem man zumindest das Zusammensetzen des Strings etwas schöner umsetzen könnte. Vielleicht habe ich da aber auch andere Möglichkeiten übersehen.

        Ein weiterer Schwachpunkt ist, dass der String erst beim Ausschalten des Verbrauchers (oder ggf. periodisch) aktualisiert wird. Deshalb hab ich in mit in die Persistence-Datenbank aufgenommen, damit er nach dem Start korrekt angezeigt wird. Alternativ könnte man ihn auch grundsätzlich peridisch aktualisieren oder Regeln erstellen, die auf das Ändern des Zählers triggern. Das sind mir dann aber doch deutlich zu viele Regeln. Bei meiner aktuellen Version mit 41 Verbrauchern reagiert der Designer beim Bearbeiten der Regel-Datei schon deutlich behäbig.

        Als Kompromiss wäre auch eine Regel denkbar, die auf das Ändern aller Zähler triggert und dann jedes mal alle Strings aktualisiert. So etwas ist natürlich beim Start blöd.

        Vielleicht habt ihr da ja noch Vorschläge?

        P.S.: Warum der Browser das End im letzten Codeblock schluckt ist mir nicht klar, in meinem Posting ist es enthalten...

        Kommentar


          #19
          Noch ein Hinweis: Die Initalisierung der Variablen zum Speichern der letzten Startzeit kommt anstatt in die Startup-Regel besser direkt hinter die Variablendeklaration also

          Code:
          var Steckdosen_Wohnen_Heizung_links_OnTime = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin"))
          Mit der ersten Variante ergibt sich das Problem, dass die Variable beim erneuten Einlesen der Regeldatei (z.B. nach dem Ändern) neu deklariert wird. Damit ist sie dann aber undefiniert, da die Startup-Regel nur beim Start ausgeführt wird. Das gibt dann beim Ersten Aufruf der periodischen Überwachung bei schon eingeschaltetem Verbraucher eine Null-Pointer Exception.

          Gibt es eigentlich auch einen Trigger der beim erneuten Einlesen wirksam wird?

          Kommentar


            #20
            Zitat von Jockel Beitrag anzeigen
            Gibt es eigentlich auch einen Trigger der beim erneuten Einlesen wirksam wird?
            hmm ... bin jetzt nicht ganz sicher, aber eigentlich werden beim Einlesen die Rules mit dem Trigger "System started" ausgeführt.

            Hast Du das schon probiert?
            Visualisierung, Rule/Logic-Engine, Integrationsplattform mit openhab (Supportforum)

            Kommentar


              #21
              Hast Du das schon probiert?
              In der ersten Variante hatte ich die Initialisierung der letzten Startzeit (also z.B. Steckdosen_Wohnen_Heizung_links_OnTime) in einer "System started" Regel.

              Dann gab es aber das Problem, dass es nach einer Änderung der Regeldatei (und erneutem Einlesen durch openHAB) beim Zugriff auf diese Variable in der periodischen Überprüfung eine Null-Pointer Exception geworfen wurde. Nachdem ich die Initialisierung bei der Deklaration vorgenommen habe gab es das nicht mehr. Weiter ausführlich getestet hab ich es aber nicht.

              Kommentar


                #22
                hmm ... bin jetzt nicht ganz sicher, aber eigentlich werden beim Einlesen die Rules mit dem Trigger "System started" ausgeführt.
                Du hast völlig recht! Ich hab noch mal etwas getestet, nach dem Einlesen der .rules Datei wird die "System started" Regel ausgeführt!

                Wahrscheinlich habe ich das mit dem Einlesen der Items verwechselt, danach wird in der Tat nicht neu initialisiert.

                Außerdem wundere ich mich im Moment über eine sporadische Meldung "Cannot assign a value in null context." beim Ausführen von Zeilen wie "Lampen_Torpfeiler_OnTime = java::util::Calendar::getInstance(TimeZone::getTim eZone("Europe/Berlin")) " nach dem Einlesen der .items.

                Das kommt aber nicht in jedem Fall und bei unterschiedlichen Items vor.
                Deklariert sind die Variablen in der .rules als var Lampen_Torpfeiler_OnTime und es macht keinen Unterschied, ob ich sie in der "System started" Regel oder bei der Deklaration initialisiere.

                Kommentar


                  #23
                  Zitat von Jockel Beitrag anzeigen
                  sporadische Meldung "Cannot assign a value in null context." beim Ausführen von Zeilen wie "Lampen_Torpfeiler_OnTime = java::util::Calendar::getInstance(TimeZone::getTim eZone("Europe/Berlin")) " nach dem Einlesen der .items.
                  hier wäre es interessant nochmal den ganzen Stacktrace zu sehen.

                  Übrigens:

                  Code:
                  var Calendar now   = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin")) 
                  var Number Diff    =  (now.getTimeInMillis() - Steckdosen_Wohnen_Heizung_links_OnTime.getTimeInMillis()) / 1000
                  für diese ganzen Zeitoperationen haben wir die Joda-Time-Lib eingebunden. In allen Regeln steht die bspw. immer das Objekt "now" zur Verfügung auf dem Du auch eine Reihe von Methoden aufrufen kannst. Einfach mal im Designer in einer Rule "now." bzw. CTRL+Space tippen und warten bis die IDE Ergebnisse liefert (Codevervollständigung).

                  Schau einfach mal hier Java date and time API - User Guide, was man damit noch so alles anstellen kann :-).

                  Gruß,

                  Thomas E.-E.
                  Visualisierung, Rule/Logic-Engine, Integrationsplattform mit openhab (Supportforum)

                  Kommentar


                    #24
                    Danke, dass Du mich da noch mal drauf gestupst hast. Joda DateTime hatte ich mmir schon vor einiger Zeit angeschaut, bin dann aber daran gescheitert dass ich keine Variable vom Typ DateTime deklarieren konnte. Jetzt hab ich noch mal mit dem Designer herumgespielt, offensichtlich hatte ich damals ein import org.joda.time.* vergessen, zumindest findet der Designer damit dann keinen Fehler mehr.

                    Den Trace poste ich heute abend!

                    Kommentar


                      #25
                      Zitat von Jockel Beitrag anzeigen
                      import org.joda.time.*
                      dieser Import sollte eigentlich nicht nötig sein ... benutzt Du den neuesten Designer?
                      Visualisierung, Rule/Logic-Engine, Integrationsplattform mit openhab (Supportforum)

                      Kommentar


                        #26
                        Getestet habe ich es eben mit dem aus dem 1.1 Stable Release, zu Hause kann ich es noch mal mit dem Snapshot Build probieren.

                        Hab dazu in einer Regel eine Variable deklariert: var DateTime test

                        Ohne den Import wird sie mir rot unterschlängelt, Fehler: Couldn't resolve reference to JvmType 'DateTime'.

                        Ctrl+Space bei test. liefert dabei ein, wie es scheint, generisches Ergebnis aufgrund irgendwelcher Basisklassen. Erstaunlich finde ich, dass es bei now. eine Liste der Methoden von DateTime gibt, auch wenn das import nicht vorhanden ist.

                        Mit dem import ist die Liste mit ctrl+space bei test. und now., zumindest auf den ersten Blick, identisch.

                        Kommentar


                          #27
                          So, die komplette Meldung laute wie folgt:
                          Code:
                          2013-01-25 00:26:48.902 ERROR o.o.c.s.ScriptExecutionThread[:70]- Error during the execution of rule 'Aktualisiere Betriebsstunden Steckdosen_Arbeiten_hinten_rechts_Schalten': Cannot assign a value in null context.
                          Einen Trace gibt es da nicht.

                          Die Regel dazu lautet:

                          Code:
                          rule "Aktualisiere Betriebsstunden Steckdosen_Arbeiten_hinten_rechts_Schalten"
                          when
                              Item Steckdosen_Arbeiten_hinten_rechts_Schalten changed
                          then
                          	if (Steckdosen_Arbeiten_hinten_rechts_Schalten.state == ON) {
                                  Steckdosen_Arbeiten_hinten_rechts_OnTime = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin"))  
                                  
                          	} else if (Steckdosen_Arbeiten_hinten_rechts_Schalten.state == OFF && previousState == ON) {
                              	var Calendar now   = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin")) 
                                  var Number Diff    =  (now.getTimeInMillis() - Steckdosen_Arbeiten_hinten_rechts_OnTime.getTimeInMillis()) / 1000
                                  var Number Prev    = 0
                          
                                  if (Steckdosen_Arbeiten_hinten_rechts_Zaehler.state instanceof DecimalType) {
                                  	Prev = Steckdosen_Arbeiten_hinten_rechts_Zaehler.state as DecimalType
                                  }
                                  var Number Zaehler = Prev + Diff
                          
                                  Steckdosen_Arbeiten_hinten_rechts_Zaehler.postUpdate(Zaehler)
                                  
                                  var Number h = (Zaehler/3600).intValue
                          		var Number m = ((Zaehler-h*3600)/60).intValue
                                 	var Number s = ((Zaehler-h*3600 - m*60)).intValue
                          		var String TimeString = h + ":" 
                          		if (m < 10) {TimeString = TimeString + "0" + m.toString + ":"} else {TimeString = TimeString + m.toString + ":"}
                          		if (s < 10) {TimeString = TimeString + "0" + s.toString}       else {TimeString = TimeString + s.toString} 
                                 	
                          		Steckdosen_Arbeiten_hinten_rechts_Betriebsstunden.postUpdate(TimeString)
                          		
                                  logInfo("operating hours rules", "Updated operating counter for Steckdosen_Arbeiten_hinten_rechts_Schalten: " + Zaehler + " Prev: " + Prev)
                          	}
                          end
                          Die Steckdose war zu diesem Zeitpunkt an, es wird also der erste if-Block ausgeführt. Er tritt auf jeden Fall nach dem Aktualisieren der Items auf, ob auch nach dem Aktualisieren der Rules kann ich noch nicht sicher sagen!

                          Kommentar


                            #28
                            Und noch eine Ergänzung zum Import von import org.joda.time.*: Das Verhalten tritt auch mit meinem 1.2 nightly Build vom 21.01. auf!

                            Kommentar


                              #29
                              Zitat von nbkhollow Beitrag anzeigen
                              Achso, ich wusste jetz den Preisunterschied nicht auswendig... Und vor allem wenn die Daten nicht direkt genutzt werden können ist es was anderes.

                              PS: Weis zufällig jemand ob sich eine solche Log-Datei mit Loxone realisieren lässt?
                              in der Loxone gibt es einen Zähler, wo ich anschließend per Iphone direkt die Zeiten ablesen kann, wie lange die Lampe an war. ( Stunde, Woche, Monat usw. )

                              Kommentar


                                #30
                                Zitat von Jockel Beitrag anzeigen
                                Und noch eine Ergänzung zum Import von import org.joda.time.*: Das Verhalten tritt auch mit meinem 1.2 nightly Build vom 21.01. auf!
                                hmm ... ich habe mir gerade den Designer 1.1 runter geladen, darin eine neue Regel-Datei test.rules mit folgendem Inhalt angelegt:

                                Code:
                                import org.openhab.core.library.types.*
                                
                                var long steckdosen_Arbeiten_hinten_rechts_OnTime
                                
                                rule "Aktualisiere Betriebsstunden Steckdosen_Arbeiten_hinten_rechts_Schalten"
                                when
                                    Item Steckdosen_Arbeiten_hinten_rechts_Schalten changed
                                then
                                	if (Steckdosen_Arbeiten_hinten_rechts_Schalten.state == ON) {
                                        steckdosen_Arbeiten_hinten_rechts_OnTime = now.millis  
                                	}
                                	else if (Steckdosen_Arbeiten_hinten_rechts_Schalten.state == OFF && previousState == ON) {
                                        var Number Diff    =  (now.millis - steckdosen_Arbeiten_hinten_rechts_OnTime) / 1000
                                        var Number Prev    = 0
                                
                                        if (Steckdosen_Arbeiten_hinten_rechts_Zaehler.state instanceof DecimalType) {
                                        	Prev = Steckdosen_Arbeiten_hinten_rechts_Zaehler.state as DecimalType
                                        }
                                        var Number Zaehler = Prev + Diff
                                
                                        Steckdosen_Arbeiten_hinten_rechts_Zaehler.postUpdate(Zaehler)
                                        
                                        var Number h = (Zaehler/3600).intValue
                                		var Number m = ((Zaehler-h*3600)/60).intValue
                                       	var Number s = ((Zaehler-h*3600 - m*60)).intValue
                                		var String TimeString = h + ":" 
                                		if (m < 10) {TimeString = TimeString + "0" + m.toString + ":"} else {TimeString = TimeString + m.toString + ":"}
                                		if (s < 10) {TimeString = TimeString + "0" + s.toString}       else {TimeString = TimeString + s.toString} 
                                       	
                                		Steckdosen_Arbeiten_hinten_rechts_Betriebsstunden.postUpdate(TimeString)
                                		
                                        logInfo("operating hours rules", "Updated operating counter for Steckdosen_Arbeiten_hinten_rechts_Schalten: " + Zaehler + " Prev: " + Prev)
                                	}
                                end
                                die passende Items-Datei enthält:

                                Code:
                                Switch Steckdosen_Arbeiten_hinten_rechts_Schalten
                                Number Steckdosen_Arbeiten_hinten_rechts_Zaehler
                                Number Steckdosen_Arbeiten_hinten_rechts_Betriebsstunden
                                und was soll ich sagen ... es gibt keine Fehlermeldungen :-)

                                Gruß,

                                Thomas E.-E.
                                Visualisierung, Rule/Logic-Engine, Integrationsplattform mit openhab (Supportforum)

                                Kommentar

                                Lädt...
                                X