Poolsteuerung Umwälzzeit

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Benutzeravatar
udo1toni
Beiträge: 15269
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Poolsteuerung Umwälzzeit

Beitrag von udo1toni »

Raini hat geschrieben: 11. Jul 2021 15:47 Ich würde gerne die gesamte bisherige Einschaltzeit meiner Poolpumpe am heutigen Tag wissen.
Also wenn sie z.B. von 3-4 und von 10-12 gelaufen ist (also 3h), hätte ich gerne das Ergebnis 180Min.
[...]
Könntest du mir hier noch ein paar Hinweise geben, wie das konkret aussehen würde in der Rule (OH 2.5)?
Der Trick dabei ist, das Item regelmäßig zu persistieren, also z.B. jede Minute. Dabei muss das persistierte Item eine 1 für ON speichern und eine 0 für OFF. Z.B. rrd4j sollte das automatisch so machen. Nun kannst Du in einer Rule z.B. für den aktuellen Tag mit

Code: Alles auswählen

myItem.sumSince(now.withTimeAtStartOfDay)
die Anzahl ON-Minuten seit Mitternacht erhalten.
openHAB4.3.6 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

togi99
Beiträge: 9
Registriert: 29. Jul 2018 13:29
Answers: 0

Re: Poolsteuerung Umwälzzeit

Beitrag von togi99 »

Halo zusammen,

ich würde mich hier gerne einklinken, da ich das im Thread beschriebene gerade auch versuche umzusetzen.
==> Laufzeit einer Poolpumpe zu ermitteln!

Im Thread habe ich gesehen, dass zwei unterschiedliche Herangehensweisen aufgezeigt werden.
1. per Regel die Ein- und Ausschaltzeit zu bestimmen und die Differenz als Laufzeit ausgeben/speichern
2. per Regel die Schaltzeiten (des persistierten Items) "überwachen" und mittels myItem.sumSince(now.withTimeAtStartOfDay) berechnen lassen

Für mich sind beide Ansätze brauchbar. Bekomme aber beide nicht zum Laufen. ;-)

zu 1:

Die Rule, welche ich aus dem Beiträgen hier zusammenkopiert lautet:

Code: Alles auswählen

rule "Pool Pumpe Tageslaufzeit rechnen"
when
    Item Sonoff_1 changed
then
    if(previousState == NULL)
	return;
	if(Sonoff_1.state == ON)
        StartTime = now.millis
    else {
        StopTime = now.millis
        RunTime = ((StopTime - StartTime)/1000).intValue
        logInfo("Pool Pumpe","Einschaltzeit: {} Sekunden",RunTime)
	pool_pumpe_laufzeit_tag.postUpdate((pool_pumpe_laufzeit_tag.state as Number + Runtime))
	logInfo("Pool Pumpe","Tageslaufzeit bisher: {} Sekunden",pool_pumpe_laufzeit_tag.state)

    }
end
Über das Log sehe ich, dass die Rechnung der Runtime korrekt ist. Allerdings wird ein Fehler ausgegeben.

[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Pool Pumpe Tageslaufzeit rechnen': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.lib.NumberExtensions.operator_plus(java.lang.Number,java.lang .Number) on instance: null

zu 2:
Hier bekomme ich lediglich das Ergebnis "0".

Code: Alles auswählen

rule "Pool Laufzeit TEST"
when
    Item test_pumpe changed
then
test_pumpe_laufzeit.postUpdate(test_pumpe.sumSince(now.withTimeAtStartOfDay))
logInfo("Pool Pumpe Test","Laufzeit heute: " + test_pumpe_laufzeit.state)
end 
test_pumpe ist mein Switch Item, bei welchem minütlich der Status per RRD4j weggeschrieben wird.

Kann mir jemand sagen, was ich falsch gemacht habe.
Danke.

Gruß
Tobias

Benutzeravatar
udo1toni
Beiträge: 15269
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Poolsteuerung Umwälzzeit

Beitrag von udo1toni »

Zur ersten Rule fehlt ein wichtiger Bestandteil, der mit hoher Wahrscheinlichkeit im Originalcode vorhanden war, nämlich die Definition der Variablen. StartTime, StopTime und RunTime. Mindestens StartTime muss global definiert sein, die anderen beiden können auch lokal definiert werden. Sieht dann mit ein paar Verbesserungen so aus:

Code: Alles auswählen

var Long StartTime = null

rule "Pool Pumpe Tageslaufzeit rechnen"
when
    Item Sonoff_1 changed
then
    if(previousState == NULL)                                                                  // kein alter Wert -> Abbruch da Systemstart
        return;

    var Integer iTagSec = 0                                                                    // Default Wert 
    if(pool_pumpe_laufzeit_tag.state instanceof Number)                                        // Falls Item gültigen Wert liefert
        iTagSec = (pool_pumpe_laufzeit_tag.state as Number).intValue                           // nimm diesen Wert

    if(newState == ON)                                                                         // neuer Status ON -> Startzeit merken
        StartTime = now.millis

    else if(StartTime !== null) {                                                              // neuer Status OFF UND StartTime ist nicht null
        val Integer iRunSec = ((now.Millis - StartTime)/1000).intValue                         // Differenz bilden und durch 1000 teilen
        logInfo("Pool Pumpe","Einschaltzeit: {} Sek, ({} Sek heute)",iRunSec, iTagSec + iRunSec)
        pool_pumpe_laufzeit_tag.postUpdate(iTagSec + iRunSec)
    }
end
Die erste Zeile definiert ein Objekt vom Typ Long (now.millis liefert Long). Diese Variable (var) ist global definiert und hält ihren Wert solange die Rule-Datei nicht verändert oder das System neu gestartet wird.
Die erste Zeile des eigentlichen Codes prüft, ob das Item einen gültiger Wert hatte, bevor die Rule getriggert wurde. Ist das nicht der Fall, so wurde das System neu gestartet und die Rule muss abgebrochen werden.
Im nächsten Block wird der Wert des Anzeige Items bestimmt. Ist dieser Wert keine Zahl, so wird 0 als Zahl verwendet (ansonsten gäbe es später nullPointerExeptions). Es bietet sich an, das über eine weitere Variable zu erledigen.

Nun wird geprüft, welchen Zustand das triggernde Item aktuell hat. Bei ON merkt sich die Rule die aktuelle Zeit, bei OFF wird die Berechnung der Laufzeit ausgeführt, unter der Voraussetzung, dass der Startzeit Speicher auch einen Wert enthält (sonst nullPointerException...)
Das Ergebnis der Berechnung ist die aktuelle Einschaltdauer in Sekunden, die direkt in einer lokalen Konstanten gespeichert wird (val, nicht var)
Die neue Summe wird gemeinsam mit der Einschaltdauer ausgegeben und ins Item geschrieben.

Es ist nicht korrekt, ein Item zu beschreiben (mit postUpdate) und unmittelbar wieder auszulesen (mit .state), denn openHAB arbeitet asynchron. Es gbit keine garantierten Laufzeiten, das heißt, es kann vorkommen, dass .state unmittelbar nach .postUpdate den Wert VOR dem .postUpdate liefert, es kann aber auch den Wert NACH dem .postUpdate liefern. Das Verhalten ist nicht deterministisch und von vielen Faktoren abhängig.
openHAB4.3.6 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

togi99
Beiträge: 9
Registriert: 29. Jul 2018 13:29
Answers: 0

Re: Poolsteuerung Umwälzzeit

Beitrag von togi99 »

Hallo Udo,

herzlichen Dank für deine Unterstützung.
Wieder sehr viel gelernt. Vor allem bezüglich dieser postUpdate Sache...

Antworten