Poolreinigung

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Antworten
maddin2020
Beiträge: 26
Registriert: 29. Sep 2019 11:21
Answers: 0

Poolreinigung

Beitrag von maddin2020 »

Hi zusammen,

ich habe eine kurze Frage zu meine Rule für die Poolreingung. Ich habe das Beispiel hier aus dem Forum nur irgendwie meckert der Editor immer bei der Timer Definition. (z.B. The method timer1(Object) is undefined).

Ich verstehe nicht was ich dort falsch mache kann dort mal jemand auf die Rule schauen. Ich bekomme sie einfach nicht zu laufen. Eigentlich was ganz einfaches Pumpe 1 und nach Wunschzeit aus. Mit Rest und idealer Istlaufzeitanzeige.

Danke

Code: Alles auswählen

rule "Poolreinigung starten"
when
    Item Poolreinigung_starten changed to ON		//das Item das den Timer aktivern soll angeben
then
    val gartenactions = getActions("pushover", "pushover:pushover-account:account")
    gartenactions.sendMessage("Poolreingung gestartet", "@ Home")
    sendCommand(Shelly_Pool_oben , ON)
    val timerlaufzeit = Poolreingungszeit.state as Number
        Laufzeit_Poolreinigung.postUpdate(timerlaufzeit)
        timer1 = createTimer(now.plusMinutes(timerlaufzeit.intValue)) [|
        sendCommand(Shelly_Pool_oben , OFF)
        ]
end

Code: Alles auswählen

rule "Verbleibende Zeit"
when 
    Item Poolreinigung_starten changed to ON 
then 
    Verbleibende_Laufzeit_Poolreinigung.postUpdate(Poolreingungszeit.state)
    timer2 = createTimer(now.plusMinutes(1), [ |
        var int remain = (Verbleibende_Laufzeit_Poolreinigung.state as DecimalType - 1 ).intValue
        if( remain < 0 ) 
            remain = 0
        Verbleibende_Laufzeit_Poolreinigung.postUpdate(remain)
        if( remain > 0) 
        timer2.reschedule(now.plusMinutes(1))
        ])
end       

Code: Alles auswählen

rule "Timer abbrechen"
when
    Item Poolreinigung_starten changed to OFF    
then
    timer1?.cancel
    timer1 = null
    Verbleibende_Laufzeit_Poolreinigung.postUpdate(0)
    sendCommand(Shelly_Pool_oben , OFF)

    timer2?.cancel
    timer2 = null
    Laufzeit_Poolreinigung.postUpdate(0)
end

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

Re: Poolreinigung

Beitrag von udo1toni »

Der eigentliche Fehler ist, dass Du die Timer Variable nicht definiert hast. Aber die Rules sind in der Form auch nicht optimal.

Code: Alles auswählen

// Globale Variablen immer vor der ersten Rule definieren
var Timer   tPool       = null                                                      // Pool-Timer
var Integer iPoolRemain = 0

rule "Poolreinigung starten"
when
    Item Poolreinigung_starten received command                                     // nicht changed!
then
    tPool?.cancel                                                                   // falls ein Timer existiert, abbrechen
    if(receivedCommand == OFF) {                                                    // falls Befehl OFF
        Verbleibende_Laufzeit_Poolreinigung.postUpdate(0)                           // Item auf 0 
        Laufzeit_Poolreinigung.postUpdate(0)                                        // Item auf 0 
        Shelly_Pool_oben.sendCommand(OFF)                                           // Pool aus
        return;                                                                     // und Ende
    }
                                                                                    // Befehl war ON, also
    var Integer iLaufzeit = 20                                                      // default Laufzeit falls IOtem ungültig
    if(Poolreingungszeit.state instanceof Number)                                   // gültiger Wert im Item?
        iLaufzeit = (Poolreingungszeit.state as Number).intValue                    // Wert übernehmen
    if(iLaufzeit < 1) {                                                             // Falls unsinniger Wert
        Shelly_Pool_oben.sendCommand(OFF)                                           // ... nur zur Sicherheit
        return;                                                                     // und Ende
    }
    iPoolRemain = iLaufzeit                                                         // Counter setzen
    Laufzeit_Poolreinigung.postUpdate(iLaufzeit)                                    // und in statische Anzeige
    Verbleibende_Laufzeit_Poolreinigung.postUpdate(iLaufzeit)                       // und in dynamische Anzeige
    Shelly_Pool_oben.sendCommand(ON)                                                // Pool an
    val pushActions = getActions("pushover", "pushover:pushover-account:account")   // Handle für Pushover Actions holen
    pushActions.sendMessage("Poolreingung gestartet", "@ Home")                     // Nachricht schicken

    tPool = createTimer(now.plusMinutes(1), [                                       // Timer starten
        iPoolRemain --                                                              // verbleibende Zeit verringern
        Verbleibende_Laufzeit_Poolreinigung.postUpdate(iPoolRemain)                 // Anzeige updaten
        if(iPoolRemain > 0)                                                         // Falls noch Zeit übrig ist
            tPool.reschedule(now.plusMinutes(1))                                    // Timer erneut planen
        else                                                                        // ansonsten
            Shelly_Pool_oben.sendCommand(OFF)                                       // ausschalten
        ])
end
Es reicht also eine Rule, die sich um alles kümmert.
Du könntest das Item auch zum Zählen verwenden, es ist aber sinnvoller, das mit einer globalen Variablen zu machen, der Zugriff ist einfach um Größenordnungen schneller. Du könntest auch auf mindestens eines der Items verzichten (im Grunde auch auf zwei)
Nutze das Item Poolreinigungszeit zum Starten. Mutmaßlich wirst Du nicht jedes Mal andere Laufzeiten nutzen, sondern allenfalls drei oder vier verschiedene Werte? Du könntest dann ohne Probleme das Item mit Schaltflächen in der UI mit fixen Werten bestücken (alternativ auch als DropDown-Liste)

Code: Alles auswählen

// Globale Variablen immer vor der ersten Rule definieren
var Timer   tPool       = null                                                      // Pool-Timer
var Integer iPoolRemain = 0

rule "Poolreinigung"
when
    Item Poolreinigungszeit received command                                        // nicht changed!
then
    if(!(receivedCommand instanceof Number))                                        // auf sinvollen Wert prüfen
        return;                                                                     // gegebenenfalls Ende

    tPool?.cancel                                                                   // falls ein Timer existiert, abbrechen
    if(receivedCommand == 0) {                                                      // falls Befehl 0
        Shelly_Pool_oben.sendCommand(OFF)                                           // Pool aus
        return;                                                                     // und Ende
    }
    var Integer iLaufzeit = (receivedCommand as Number).intValue                    // Laufzeit übernehmen
    Laufzeit_Poolreinigung.postUpdate(iLaufzeit)                                        // statische Anzeige
    iPoolRemain = iLaufzeit                                                         // Counter setzen
    Shelly_Pool_oben.sendCommand(ON)                                                // Pool an
    val pushActions = getActions("pushover", "pushover:pushover-account:account")   // Handle für Pushover Actions holen
    val strMessage = "Poolreingung gestartet, Laufzeit " + iLaufzeit.toString + " Minuten."
    pushActions.sendMessage(strMessage, "@ Home")                                   // Nachricht schicken

    tPool = createTimer(now.plusMinutes(1), [                                       // Timer starten
        iPoolRemain --                                                              // verbleibende Zeit verringern
        Poolreinigungszeit.postUpdate(iPoolRemain)                                  // Anzeige updaten
        if(iPoolRemain > 0)                                                         // Falls noch Zeit übrig ist
            tPool.reschedule(now.plusMinutes(1))                                    // Timer erneut planen
        else                                                                        // ansonsten
            Shelly_Pool_oben.sendCommand(OFF)                                       // ausschalten
        ])
end
Die Rule fällt nun wesentlich kürzer aus und Du brauchst nur zwei Items (das zweite nur, um die zuletzt gewählte Zeit dauerhaft zu sehen)

In einer Sitemap wäre das Item dann so abgebildet:

Code: Alles auswählen

Switch item=Poolreinigungszeit label="Poolreinigung noch [%d Min]" mappings=[0="Aus",20="20",40="40",60="1h"]
Ein Item, drei Laufzeiten. Falls es mehr Laufzeiten sein sollen, geht auch das:

Code: Alles auswählen

Selection item=Poolreinigungszeit label="Poolreinigung noch [%d Min]" mappings=[0="Aus",20="20",40="40",60="1h",80="1h20",100="1h40",12="zwölf"]
Aber ich gehe stark davon aus, dass Du quasi nur eine "Schnellreinigung", ein "Normalprogramm" und eine "Intensivreinigung" brauchst.
In der Main UI geht das natürlich genauso gut.

So oder so brauchst man aber nur einen Timer, der sich sowohl um die Abschaltung als auch um die Anzeige kümmert, wichtig ist aber, dass dieser Timer seinen Zeiger in einer globalen Variablen speichern kann.

Edit: Im Code Zuweisungs-Operator gegen unären Operator getauscht
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

maddin2020
Beiträge: 26
Registriert: 29. Sep 2019 11:21
Answers: 0

Re: Poolreinigung

Beitrag von maddin2020 »

Danke Udo für die sehr ausführliche Antwort. Ich werde gleich testen und berichten. Super das man hier immer so schnell geholfen bekommt. ;-)

maddin2020
Beiträge: 26
Registriert: 29. Sep 2019 11:21
Answers: 0

Re: Poolreinigung

Beitrag von maddin2020 »

Hi Udo,

ich habs nun gerade kopiert leider funktioniert es irgendwie noch nicht so richtig.

Code: Alles auswählen

var Timer   tPool       = null                                                      // Pool-Timer
var Integer iPoolRemain = 0

Code: Alles auswählen

Number                      Poolreinigungszeit                                             "Poolreinigungszeit"                                     <time_timer>
Number                      Laufzeit_Poolreinigung                                        "Laufzeit [%d min]"                                      <time_timer>

Code: Alles auswählen

rule "Poolreinigung"
when
    Item Poolreinigungszeit received command                                        // nicht changed!
then
    if(!(receivedCommand instanceof Number))                                        // auf sinvollen Wert prüfen
        return;                                                                     // gegebenenfalls Ende

    tPool?.cancel                                                                   // falls ein Timer existiert, abbrechen
    if(receivedCommand == 0) {                                                      // falls Befehl 0
        Shelly_Pool_oben.sendCommand(OFF)                                           // Pool aus
        return;                                                                     // und Ende
    }
    var Integer iLaufzeit = (receivedCommand as Number).intValue                    // Laufzeit übernehmen
    Laufzeit_Poolreinigung.postUpdate(iLaufzeit)                                        // statische Anzeige
    iPoolRemain = iLaufzeit                                                         // Counter setzen
    Shelly_Pool_oben.sendCommand(ON)                                                // Pool an
    val pushActions = getActions("pushover", "pushover:pushover-account:account")   // Handle für Pushover Actions holen
    val strMessage = "Poolreingung gestartet, Laufzeit " + iLaufzeit.toString + " Minuten."
    pushActions.sendMessage(strMessage, "@ Home")                                   // Nachricht schicken

    tPool = createTimer(now.plusMinutes(1), [                                       // Timer starten
        iPoolRemain = -1                                                            // verbleibende Zeit verringern
        Poolreinigungszeit.postUpdate(iPoolRemain)                                  // Anzeige updaten
        if(iPoolRemain > 0)                                                         // Falls noch Zeit übrig ist
            tPool.reschedule(now.plusMinutes(1))                                    // Timer erneut planen
        else                                                                        // ansonsten
            Shelly_Pool_oben.sendCommand(OFF)                                       // ausschalten
        ])
end
ich habe eine kleine Stelle schon verändert ich glaub da war ein Tippfehler drin dann der Editor hat ein Fehler gemeldet.

Code: Alles auswählen

iPoolRemain -= 1  //habe ich abgeändert auf
iPoolRemain = -1 
Trotzdem startet der Timer schon geht aber direkt nach 1 min wieder aus und die verbleibende Zeit steht in der Sitemap -1. Kannst du dort nochmal drüberschauen wo nun der Fehler steckt. Die Timer habe ich ganz oben in der rules Datei definiert.

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

Re: Poolreinigung

Beitrag von udo1toni »

maddin2020 hat geschrieben: 18. Jun 2023 14:02 ich habe eine kleine Stelle schon verändert ich glaub da war ein Tippfehler drin dann der Editor hat ein Fehler gemeldet.

Code: Alles auswählen

iPoolRemain -= 1  //habe ich abgeändert auf
iPoolRemain = -1
Ja, aber nein.

Ich bin nur mit den Operatoren durcheinander geraten. -= (und +=) gibt es für Variablen vom Typ int, während Variablen vom Typ Integer (ja, das ist ein großer Unterschied) diesen Operator nicht kennen.

Variable -= 1 bedeutet: Ziehe 1 von der Variablen ab und speichere das Ergebnis in der selben Variablen. korrekt wäre also

Code: Alles auswählen

iPoolRemain = iPoolRemain - 1
aber Integer beherrscht eine andere Abkürzung, nämlich ++ und --

Code: Alles auswählen

iPoolRemain --
bedeutet: ziehe 1 von iPoolRemain ab und speichere das Ergebnis in iPoolRemain (das wäre also die richtige Änderung)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

maddin2020
Beiträge: 26
Registriert: 29. Sep 2019 11:21
Answers: 0

Re: Poolreinigung

Beitrag von maddin2020 »

super danke dir jetzt geht es

Antworten