Shelly 2.5 und Rolladensteuerung (Rule)

Geflasht oder ungeflasht ...

Moderator: seppy

Antworten
edirk
Beiträge: 14
Registriert: 29. Aug 2019 19:53

Shelly 2.5 und Rolladensteuerung (Rule)

Beitrag von edirk »

Hallo,

ich habe folgendes Problem: (Shelly ist mit Tasmota geflasht)
Grundsätzlich funktioniert die Steuerung der Rollade über diese Regel bzw. die Bedienung in der Oberfläche (Openhab(Basic)).
Derzeit ist es jedoch so, dass wenn ich die Rollade hoch oder runter fahre (Openhab) bleibt der jew. Ausgang geschaltet bis ich ihn
gezielt AUS schalte oder ein OFF Signal sende.
Dieses gezielte OFF Signal möchte ich abhängig von der Leistung senden. D.H. Leistung geht auf 0 beide Ausgänge gehen auf OFF

hier die Regel:

import org.joda.time // derzeit nicht genutzt
import org.openhab.model.script.actions.Timer // derzeit nicht genutzt

var Timer rollo_timer = null // derzeit nicht genutzt

rule "Rollershutter Rollo_Wohnzimmer Stop or Set Position"
when
Item Rollo_Wohnzimmer received command
then
if (receivedCommand == STOP) {
Rollo_WZ_Power1.sendCommand("OFF")
Rollo_WZ_Power2.sendCommand("OFF")
Rollo_Teleperiod.sendCommand(300)
}
else if (receivedCommand == UP) {
if (Rollo_WZ_Power2.state == "OFF") {
Rollo_WZ_Power1.sendCommand("on")
Rollo_Teleperiod.sendCommand(10)
}
}

else if (receivedCommand == DOWN) {
if (Rollo_WZ_Power1.state == "OFF") {
Rollo_WZ_Power2.sendCommand("on")
Rollo_Teleperiod.sendCommand(10)
}
}


end



rule "Bei Leistungsänderung auf 0 beide Kanäle OFF"

when
Item Rollo_Wohnzimmer received command UP or
Item Rollo_Wohnzimmer received command DOWN

then
rollo_timer?.cancel // derzeit nich benötigt


logInfo("Regel2", "Start")

if (Rollo_Wohnzimmer.state == 0) {
logInfo("Regel2", "Start Bedingung1") // Bis hier soweit i.O.
// Rollo_CMD.sendCommand(8)
Thread::sleep(15000) // da vorab die Teleperiod auf 10sec gesetzt wurde und nicht durch den "alten" Watt Wert wieder getriggert wird
if (Rollo_WZ_Watts = 0 ) { //Test ohne state
logInfo("Regel2", "Leistung= " + Rollo_WZ_Watts.state) // sollte hier wieder auf 0 sein
Rollo_WZ_Power1.sendCommand("OFF")
Rollo_WZ_Power2.sendCommand("OFF")
Rollo_Teleperiod.sendCommand(300)
logInfo("Regel2", "Ende Bedingung1")
}
}

else if (Rollo_Wohnzimmer.state == 100) {
logInfo("Regel2", "Start Bedingung2")
// Rollo_CMD.sendCommand(8)
Thread::sleep(15000)
if (Rollo_WZ_Watts.state = 0 ) {
logInfo("Regel2", "Leistung= " + Rollo_WZ_Watts.state)
Rollo_WZ_Power1.sendCommand("OFF")
Rollo_WZ_Power2.sendCommand("OFF")
Rollo_Teleperiod.sendCommand(300)
logInfo("Regel2", "Bedingung2")
}

}

else
logInfo("Regel2", "Else")



end

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

Re: Shelly 2.5 und Rolladensteuerung (Rule)

Beitrag von udo1toni »

Bitte markiere Code immer als Code, das macht ihn leichter lesbar. (im vollständigen Editor der Knopf mit dem </>)

Deine Rules weisen gleich mehrere Merkwürdigkeiten auf. Wie sind die Items definiert?
Ein Switch Item kennt nur die Befehle ON und OFF, weder "ON" noch "OFF" noch "on" oder "off".

Wenn man den Status eines Items haben will, so geht das ausschließlich über die Eigenschaft .state. Wenn man auf Gleichheit prüfen will, geht das ausschließlich mit ==. Thread::sleep() sollte nicht mit Werten über 500 genutzt werden. Die Imports sind unter OH2 beide nicht nötig.

Eine einfache Rule sollte eher so aussehen:

Code: Alles auswählen

//globale Variablen immer im Kopf der Datei definieren
var Timer tAutoOff = null

rule "Rollo up/down"#
when
    Item Rollo_Wohnzimmer received command
then
    switch (receivedCommand) {
        case STOP: {
            Rollo_WZ_Power1.sendCommand(OFF)
            Rollo_WZ_Power2.sendCommand(OFF)
        }
        case UP: {
            if(Rollo_WZ_Power2.state != OFF) {
                Rollo_WZ_Power2.sendCommand(OFF)
                Thread::sleep(200)
            }
            Rollo_WZ_Power1.sendCommand(ON)
        }
        case DOWN: {
            if(Rollo_WZ_Power1.state != OFF) {
                Rollo_WZ_Power1.sendCommand(OFF)
                Thread::sleep(200)
            }
            Rollo_WZ_Power2.sendCommand(ON)
        }
        default: {
            // Vorhalt für Positionsfahrt
        }
    }
end

rule "Rollo auto-off"
when
    Item Rollo_WZ_Watts changed
then
    tAutoOff?.cancel
    tAutoOff = createTimer(now.plusMillis(500), [|
        if((Rollo_WZ_Watts.state as Number) == 0) {
            Rollo_WZ_Power1.sendCommand(OFF)
            Rollo_WZ_Power2.sendCommand(OFF)
        }
    ])
end
Zur Funktion: Die switch-case Anweisung ist hier gut geeignet, den Code etwas besser zu strukturieren. Falls man die Fahrtrichtung unmittelbar umschaltet, legt das Thread::sleep(200) eine kleine Pause ein, um sicherzustellen, dass die Gegenrichtung ausgeschaltet ist.
im default-Bereich könnte man auf ein Zahlen Kommando reagieren (dazu bräuchte man allerdings auch ein Item, in dem die aktuelle Position gespeichert ist, weshalb ich diesen Teil des Codes jetzt nicht implementiere... zu viele Variablen...)

Die zweite Rule triggert, sobald sich die Stromaufnahme geändert hat. Als erstes wird eine kleine Pause eingelegt, und zwar per Timer. Ändert sich die Stromaufnahme, wird der Timer abgebrochen und erneut gestartet. Das bedeutet, dass die Stromaufnamhe zum Zeitpunkt der Prüfung bereits 500 Millisekunden den gleichen Wert hat. Ist dieser Wert 0, so werden beide Motoren ausgeschaltet.

Es kann natürlich gut sein, dass die Stromaufnahme nicht bei 0 liegt, sondern bei 0,0001 ;) es wäre also sinnvoll, zu schauen, welche Strommenge der unbelastete Motor während der Drehung mindestens hat und die Prüfung auf < zu ändern (z.B. Mindeststromaufnahme ist 50 -> if(Rollo_WZ_Watts.state < 45) )

Der große Vorteil des Timers ist hier, dass der Code innerhalb des Lambdas sicher nie mehrfach parallel ausgeführt wird.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

edirk
Beiträge: 14
Registriert: 29. Aug 2019 19:53

Re: Shelly 2.5 und Rolladensteuerung (Rule)

Beitrag von edirk »

Hallo udo1toni,

mal wieder vielen Dank für die Hilfe.
Die Regel sieht jetzt folgender maßen aus (s.u.).
Ergänzend habe ich jedoch wieder die Einstellung der Teleperiod eingebaut, da diese normalerweise auf 5min läuft und nur
bei Bedienung auf 10sec Aktualisierungsfrequenz geht.
Das muss ich scheinbar tun, da sonst die 2. Regel nicht greift,weil er evtl. innerhalb der 5min Aktualisierung keinen neuen "Watt" Status bekommt.

Ich habe in diesem Fall auf die Leistung (Watt) getriggert da diese definitiv auf 0 geht (Endschalter im Rolladenmotor schaltet ab).
Bei Zwischenpositionen wird es vermutlich somit nicht funktionieren.
Wichtig für mich war das Abschalten der Ausgänge, so dass bei Bedienung am Taster/Schalter vor Ort hier nicht beide gleichzeitig aktiv werden können.
Das kann der Shelly nicht sauber regeln und schaltet somit auf beide Richtungen die Phase....(wenn auch nur kurz) (beim Ersten Rollo hat es mir dadurch gleich mal die Endpositionen des Motors zerlegt....)


Items:

Code: Alles auswählen

Rollershutter Rollo_Wohnzimmer

Number Rollo_Tele                           { mqtt=">[openHABianPi:Haus/Rollade1/shelly25_116/cmnd/teleperiod:command:*:default]"}

String Rollo_WZ_Power1                      { mqtt="<[openHABianPi:Haus/Rollade1/shelly25_116/tele/STATE:state:JSONPATH($.POWER1)], >[openHABianPi:Haus/Rollade1/shelly25_116/cmnd/POWER1:command:*:default]"}

String Rollo_WZ_Power2                      { mqtt="<[openHABianPi:Haus/Rollade1/shelly25_116/tele/STATE:state:JSONPATH($.POWER2)], >[openHABianPi:Haus/Rollade1/shelly25_116/cmnd/POWER2:command:*:default]"}


RULE:

Code: Alles auswählen

//globale Variablen immer im Kopf der Datei definieren
var Timer tAutoOff = null

rule "Rollo up/down"
when
    Item Rollo_Wohnzimmer received command
then
    switch (receivedCommand) {
        case STOP: {
            Rollo_WZ_Power1.sendCommand(OFF)
            Rollo_WZ_Power2.sendCommand(OFF)
			Rollo_Tele.sendCommand(300)
		}
        case UP: {
            if(Rollo_WZ_Power2.state != OFF) {
                Rollo_WZ_Power2.sendCommand(OFF)
                Rollo_Tele.sendCommand(10)
				Thread::sleep(200)
            }
            Rollo_WZ_Power1.sendCommand(ON)
        }
        case DOWN: {
            if(Rollo_WZ_Power1.state != OFF) {
                Rollo_WZ_Power1.sendCommand(OFF)
                Rollo_Tele.sendCommand(10)
				Thread::sleep(200)
            }
            Rollo_WZ_Power2.sendCommand(ON)
        }
        default: {
            // Vorhalt für Positionsfahrt
        }
    }
end

rule "Rollo auto-off"
when
    Item Rollo_WZ_Watts changed
then
    tAutoOff?.cancel
    tAutoOff = createTimer(now.plusMillis(500), [|
        if((Rollo_WZ_Watts.state as Number) == 0) {
            Rollo_WZ_Power1.sendCommand(OFF)
            Rollo_WZ_Power2.sendCommand(OFF)
			Rollo_Tele.sendCommand(300)
		}
    ])
end

Antworten