Seite 2 von 3

Re: Betriebsstundenzähler

Verfasst: 25. Jan 2016 12:36
von toto1975
In meiner mysql Datenbank habe ich folgende Einträge
Time | Value
2016-01-23 20:30:38 | 0
2016-01-23 20:33:48 | 0
usw.

Den Fehler erhalte ich immer dann wenn ich die Seite öfnen möchte auf dem das Item ist kommentiere ich das Item aus erhalte ich beim öffnen der Seite keine Fehlermeldung und die Seite öffnet sich.

Gruß
Torsten

Re: Betriebsstundenzähler

Verfasst: 25. Jan 2016 12:49
von seppy
Wie sieht denn Deine Itemdefinition aus?

Re: Betriebsstundenzähler

Verfasst: 27. Jan 2016 23:00
von seppy
Hallo Zusammen,

hier noch eine überarbeitete Variante:

Code: Alles auswählen

var long last_change = now.millis

rule "Betriebsdauerzähler"
when
	Item DevSchalter changed
then
	var Number sum = 0
	var Number ontime = 0
  
	if (previousState == OFF){
		last_change = now.millis
		logInfo("Homebox.DEV", "Schalter ON: " + last_change)
		logInfo("Homebox.DEV", "Aktueller Zählerstand: " + Betriebsdauer.state)
	} else if (previousState == ON) {
		if (Betriebsdauer.state == Uninitialized){
			logInfo("Homebox.DEV", "Betriebsdauer nicht initialisiert")
			Betriebsdauer.postUpdate(0)
		}
		ontime = (now.millis - last_change)		
		sum = ((Betriebsdauer.state as DecimalType).longValue) + ontime
		logInfo("Homebox.DEV", "Gerät angeschaltet: " + last_change)
		logInfo("Homebox.DEV", "Gerät abgeschaltet: " + now.millis)		
		Betriebsdauer.postUpdate(sum)
		Betriebsdauer.persist
		logInfo("Homebox.DEV", "Laufzeit Gerät Abschaltzeitpunkt in Millisekunden - Anschaltzeitpunkt in Millisekunden = Laufzeit: " + ontime.toString )
		logInfo("Homebox.DEV", "Betriebszeit (Std.) gesamt: " + (sum/60000))
	}
end
Hier auf erfolgt die Speicherung auf Millisekundenbasis, da sonst beim Umrechnen auf Std. bzw. Minuten zu viel verloren geht!

Grüße,
Seppy

Re: Betriebsstundenzähler

Verfasst: 13. Mai 2020 08:26
von littleswabi
Hallo :)

das Thema ist schon alt aber ich wüsste gern wie die ITEM Definition dafür aussieht :)

Wäre sehr dankbar für eine Antwort

Grüße

Re: Betriebsstundenzähler

Verfasst: 14. Mai 2020 06:20
von udo1toni
Ist ja eigentlich weiter oben mit drin :)

Aber Vorsicht! Die Rules sind 4 Jahre alt, mit einer aktuellen Version von openHAB (OH2.5.4) wird der Code ohne Änderungen nicht sauber laufen.

Mein Vorschlag:

Code: Alles auswählen

// globale Variablen zu Beginn der Datei definieren!
var long dtStart = now.millis

rule "Betriebsdauer"
when
    Item MySwitch changed                                                               // Überwachter Schalter
then
    if (newState == ON){                                                                // Schalter ein
        dtStart = now.millis                                                            // Zeitpunkt retten
    } else if (newState == OFF) {                                                       // Schalter aus
        var Integer iSum = 0                                                            // Variable initialisieren
        if (MySwitchBZ.state instanceof Number)                                         // Falls Zähler initialisiert
            iSum = MySwitchBZ.state as Number                                           // Zählerstand übernehmen
        else                                                                            // ansonsten
            logWarn("oc.myswitch", "Betriebsdauer für MySwitch wird initialisiert!")    // Meldung ausgeben

        iSum = iSum + ((now.millis - dtStart + 500) / 1000).intValue                    // Einschaltdauer addieren
        MySwitchBZ.postUpdate(iSum)                                                     // und speichern
    }
end
Die Betriebsdauer wird hier in Sekunden gespeichert.
Da Sekunden schnell unübersichtlich werden, wird die Ausgabe per JS formatiert. Der JS Transformation Service muss installiert sein.

Die Items:

Code: Alles auswählen

Switch MySwitch "Mein Schalter [%s]" {...}
Number MySwitchBZ "Betriebsdauer [JS(secToHMS.js):%s]" // Item persistieren (everyChange, restoreOnStartup, mapDB reicht)
und das notwendige JavaScript Script:
secToHMS.js:

Code: Alles auswählen

(function(seconds){
    var retval = "";
    var hours = Math.floor(seconds / 3600)
    seconds = seconds % 3600
    var minutes = Math.floor(seconds / 60)
    seconds = seconds % 60
    retval = retval + hours + "h";
    if (minutes < 10)
        retval = retval + "0";
    retval = retval + minutes+"m";
    if (seconds < 10)
        retval = retval + "0";
    retval = retval + seconds+"s";
    return retval;
})(input)
Die Betriebsdauer Anzeige wird erst beim Abschalten aktualisiert. Sollte der Zählerstand beim Abschalten nicht initialisiert sein, so startet der Zähler bei 0. Sollte der Schalter beim Start von openHAB bereits eingeschaltet sein, so wird der Einlesezeitpunkt der rules als Einschaltzeitpunkt angenommen.
Sollte man mehrere Zähler benötigen, so müssen auch mehrere Variablen für den Startzeitpunkt definiert werden. Dann sollte man das Konzept überdenken. :)

Re: Betriebsstundenzähler

Verfasst: 14. Mai 2020 08:42
von littleswabi
Hallo Udo,

vielen Dank für die schnelle und ausführliche Antwort. Habe das so übernommen und für meine Zwecke angepasst.

Allerdings bekomme ich bei ausschalten folgenden Fehler:

Code: Alles auswählen

2020-05-14 08:32:51.761 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Betriebsdauer': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_plus(int,int) on instance: null
meine Rule sieht so aus:

Code: Alles auswählen

// globale Variablen zu Beginn der Datei definieren!
var long dtStart = now.millis

rule "Betriebsdauer"
when
    Item Sandfilter_Power changed                                                               			// Überwachter Schalter
then
    if (newState == ON){                                                               		 			// Schalter ein
        dtStart = now.millis                                                           					 // Zeitpunkt retten
    } else if (newState == OFF) {                                                      					 // Schalter aus
        var Integer iSum = 0                                                           		 			// Variable initialisieren
        if (Sandfilterpumpe_Betriebsdauer.state instanceof Number)                                         // Falls Zähler initialisiert
            iSum = Sandfilterpumpe_Betriebsdauer.state as Number                                           // Zählerstand übernehmen
        else                                                                            // ansonsten
            logWarn("oc.myswitch", "Betriebsdauer für MySwitch wird initialisiert!")   		 // Meldung ausgeben

        iSum = iSum + ((now.millis - dtStart + 500) / 1000).intValue                  			  // Einschaltdauer addieren
        Sandfilterpumpe_Betriebsdauer.postUpdate(iSum)                                                     // und speichern
    }
end
Dein mySwitchBZ habe ich durch Sandfilterpumpe_Betriebsdauer ersetzt.

Code: Alles auswählen

Strategies {
        everyMinute     : "0 * * * * ?"
        everyHour       : "0 0 * * * ?"
        everyDay        : "0 0 0 * * ?"
 
      
        
}
Items {
        Sandfilterpumpe_Betriebsdauer     	: strategy = everyChange, restoreOnStartup
        Poolheizung_Betriebsdauer           	: strategy = everyChange, restoreOnStartup
        Sandfilter_Power                 		: strategy = everyChange, restoreOnStartup
        Heizung_Power                    		: strategy = everyChange, restoreOnStartup           
}
Was mache ich noch verkehrt? In meiner Seitmap werden 0h00m00s angezeigt.

Grüße

Michael

Re: Betriebsstundenzähler

Verfasst: 14. Mai 2020 10:14
von udo1toni
Ach, vermutlich muss die Betriebsdauer auch explizit nach int gewandelt werden:

Code: Alles auswählen

iSum = (Sandfilterpumpe_Betriebsdauer.state as Number).intValue 

Re: Betriebsstundenzähler

Verfasst: 14. Mai 2020 10:32
von littleswabi
Hi,

super!!! Funktioniert wunderbar!

VIELEN DANK!!!! :)

Re: Betriebsstundenzähler

Verfasst: 18. Mai 2020 07:39
von littleswabi
Hallo Udo,

ich habe noch eine Frage. Wenn ich die Betriebsstunden nicht vom bloßen einschalten abhängig machen will sondern vom Verbrauche reicht es dann wennn ich:

Code: Alles auswählen

when
    Item Sandfilter_Power changed        // Verbrauch der Pumpe
then
    if (newState => 10){                        // Verbrauch > 10w
        dtStart = now.millis                    // Zeitpunkt retten
    } else if (newState =< 10) { 		// Verbrauch <10 w
als Bedingung nehme?

Re: Betriebsstundenzähler

Verfasst: 18. Mai 2020 16:12
von udo1toni
Wie soll denn das gehen?
Entweder, das Gerät hat im ausgeschalteten Zustand keinen Verbrauch (also 0), oder es hat einen Verbrauch, dann müsste diese Zeit aber auch als Betriebszeit mit zählen.
Eine Unterscheidung nach Verbrauch ist auch recht kritisch, da der Verbrauch durchaus um den Schwellwert herum schwanken kann.
Mindestens solltest Du also eine Hysterese vorsehen. Z.B. beginne mit dem Zählen, wenn der Verbrauch höher als 12 ist, beende den Zählvorgang, wenn der Verbrauch unter 10 sinkt.
Die Werte müssen natürlich zum angeschlossenen Gerät passen, und der Verbrauch des Geräts darf während des Betriebs nie unter die Abschaltschwelle sinken.
Z.B. bei einer Waschmaschine ist der Energiebedarf höchst variabel und hängt auch noch stark vom genutzten Programm ab, das ist also keinesfalls trivial.
Mindestens musst Du dann über einen längeren Zeitraum Daten sammeln und auswerten, um die Rule einigermaßen schussfest zu bekommen.