Wo ist der Fehler in meiner Rule?

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Grandlhuber
Beiträge: 26
Registriert: 22. Sep 2021 07:38
Answers: 0
Wohnort: Bamberg

Wo ist der Fehler in meiner Rule?

Beitrag von Grandlhuber »

Habe mal wieder ein kleines Problem und komme nicht weiter. Habe diese Rule hier zum herunterfahren der Rollladen wenn es dunkel wird. Zudem werden je nach Sommer/Winter andere Rolladengruppen herunter gefahren:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      event: END
      channelUID: astro:sun:local:set#event
    type: core.ChannelEventTrigger
conditions: []
actions:
  - inputs: {}
    id: "13"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        if(Dummy_alle_geschlossen.state == ON)
        return;

        if(now.getMonthValue >= 4 && now.getMonthValue() <= 9)
        Rolladen.members.forEach[ r | r.sendCommand(DOWN) Thread::sleep(900)]
        Dummy_alle_geschlossen.postUpdate(ON)

        else if(now.getMonthValue >= 10 && now.getMonthValue() <= 3)
        Rollladen_Winter.members.forEach[ r | r.sendCommand(DOWN) Thread::sleep(900)]
        Dummy_alle_geschlossen.postUpdate(ON)
        
    type: script.ScriptAction
So funktioniert die DSL-Rule. Ich möchte aber einen Timer mit einbauen. Mache ich dieses, funktioniert die Rule nicht mehr:

Code: Alles auswählen

if(Dummy_alle_geschlossen.state == ON)

return;

if(now.getMonthValue >= 4 && now.getMonthValue() <= 9)
createTimer(now.plusMinutes(10), [|
Rolladen.members.forEach[ r | r.sendCommand(UP) Thread::sleep(900)]
])
 
Dummy_alle_geschlossen.postUpdate(ON)

else if(now.getMonthValue >= 10 && now.getMonthValue() <= 3)
Rollladen_Winter.members.forEach[ r | r.sendCommand(DOWN) Thread::sleep(900)]
Dummy_alle_geschlossen.postUpdate(ON)
Frage an die Spezialisten: Wo ist hier der Fehler damit es mit dem createTimer nicht mehr geht?
Ich habe z.B. dieses hier und da funktioniert das auch mit dem Timer:

Code: Alles auswählen

if(Brunnen.state == ON)

return;

createTimer(now.plusMinutes(60), [|              

Brunnen.sendCommand(ON)

])
Oli
von udo1toni » 7. Jul 2022 14:42
Ja, aber besser ist es, den Code (mindestens in der Testphase) ordentlich einzurücken:

Code: Alles auswählen

if(Dummy_alle_geschlossen.state == ON)
    return;
val Integer iMonth = now.getMonthValue 

if(iMonth > 3 && iMonth < 10)
    createTimer(now.plusMinutes(60), [|
        Rolladen.members.forEach[ r | 
            r.sendCommand(DOWN)
            Thread::sleep(900)
        ]
    ])
else
    Rollladen_Winter.members.forEach[ r |
        r.sendCommand(DOWN)
        Thread::sleep(900)
    ]
Dummy_alle_geschlossen.postUpdate(ON)
Einfach um zu erkennen, dass die erste schließende eckige Klammer zum Lambda des forEach gehört, während die zweite eckige Klammer zum Lambda des createTimer gehört (so wie auch die folgende schließend runde Klammer).
Man könnte den Code auch in eine einzige Zeile schreiben, mit jeweils einem Leerzeichen statt Zeilenumbruch, aber in dieser Form ist es doch wesentlich besser lesbar.
Gehe zur vollständigen Antwort
Konfig: OpenHab 3.3.0 auf Raspi 4B+ (Raspian).
SomfyTahoma-Bridge im LAN-Modus, Brunnen-, Zisternensteuerung, Außenlampen, Heizung (WebKM200), PV-Anlage per MQQT, Miele-Trockner, Softliq SC18, Dreambox two sowie div. Shellys zur Steckdosensteuerung per Openhab vernetzt.
Visualisierung über Grafana. Daten in Influx gesichert.

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

Re: Wo ist der Fehler in meiner Rule?

Beitrag von udo1toni »

Die Rule kann nicht funktionieren :), egal ob mit oder ohne Timer.
Deutlich wird das, wenn man die Rule etwas ordentlicher formatiert. Nur der relevante Teil:

Code: Alles auswählen

if(Dummy_alle_geschlossen.state == ON)
    return;
if(now.getMonthValue >= 4 && now.getMonthValue <= 9)
    Rolladen.members.forEach[ r | 
        r.sendCommand(DOWN)
        Thread::sleep(900)
    ]
Dummy_alle_geschlossen.postUpdate(ON)
else // <-------------------------------------------------- else ohne if!
    if(now.getMonthValue >= 10 && now.getMonthValue() <= 3) // a > 9 UND a < 4 niemals erfüllt!
        Rollladen_Winter.members.forEach[ r |
            r.sendCommand(DOWN)
            Thread::sleep(900)
        ]
Dummy_alle_geschlossen.postUpdate(ON)
if() als bedingte Verzweigung wirkt ausschließlich auf den nächsten Befehl. Damit ist Dummy_alle_geschlossen.postUpdate(ON) nicht Teil der bedingten Verzweigung. Entsprechend hat else auch kein vorgeordnetes if()
Eine Zahl (oder auch der Inhalt einer Variablen) kann niemals gleichzeitig größer als 9 UND kleiner als 4 sein.
Korrekt:

Code: Alles auswählen

if(Dummy_alle_geschlossen.state == ON)
    return;
if(now.getMonthValue > 3 && now.getMonthValue < 10) { // einfacher
    Rolladen.members.forEach[ r | 
        r.sendCommand(DOWN)
        Thread::sleep(900)
    ]
    Dummy_alle_geschlossen.postUpdate(ON)
} else
    if(now.getMonthValue > 9 || now.getMonthValue() < 4) { // einfacher
        Rollladen_Winter.members.forEach[ r |
            r.sendCommand(DOWN)
            Thread::sleep(900)
        ]
        Dummy_alle_geschlossen.postUpdate(ON)
    }
Die geschweiften Klammern definieren einen Block, der von if() als eine Anweisung betrachtet wird. Nun gibt es auch ein vorgeordnetes if() und else funktioniert. In der zweiten if() Anweisung heißt es nun der Wert muss entweder größer als 9 ODER kleiner als 4 sein.
Allerdings ist die zweite if-Anweisung unnötig, entweder wir befinden uns innerhalb oder außerhalb des Sommer-Fensters (1.4. - 30.9.)
Außerdem wird Dummy_alle_geschlossen.postUpdate(ON) auf jeden Fall ausgeführt, sollte also nicht Bestandteil des if-Blocks sein. Praktischerweise können nun die geschweiften Klammern auch wieder entfallen. now.getMonthValue wird zweimal abgefragt, also einfach in einer lokalen Konstanten speichern. Der fertige Codeblock ohne Timer:

Code: Alles auswählen

if(Dummy_alle_geschlossen.state == ON)
    return;
val Integer iMonth = now.getMonthValue 

if(iMonth > 3 && iMonth < 10)
    Rolladen.members.forEach[ r | 
        r.sendCommand(DOWN)
        Thread::sleep(900)
    ]
 else
    Rollladen_Winter.members.forEach[ r |
        r.sendCommand(DOWN)
        Thread::sleep(900)
    ]
Dummy_alle_geschlossen.postUpdate(ON)
Dein eigentliches Problem, das des Timers, ist allerdings noch ungelöst. Rein formal sollte der Timer funktionieren.
Es kann allerdings sein, dass Thread::sleep() in diesem Zusammenhang Probleme bereitet, weil es im Kontext des Lambdas definiert ist (sollte eigentlich keine Rolle spielen, aber trotzdem...).
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Grandlhuber
Beiträge: 26
Registriert: 22. Sep 2021 07:38
Answers: 0
Wohnort: Bamberg

Re: Wo ist der Fehler in meiner Rule?

Beitrag von Grandlhuber »

Hi!
Die Rule kann nicht funktionieren :), egal ob mit oder ohne Timer.
Komisch. Im Log von OpenHab gibt es keine Fehlermeldungen und die Rollladen fahren auch so runter wie sie sollen. Oder bezieht sich das nicht funktionieren auf den Sommer/Winter-Modus?

Dann erst mal danke für das Aufdröseln des Codes und dem erklären mit den Klammern. Da muss ich mal in mich gehen. Vielleicht verstehe ich dann irgendwann mal diese Sprache :) :idea: .
Dein eigentliches Problem, das des Timers, ist allerdings noch ungelöst. Rein formal sollte der Timer funktionieren.
Wäre es so richtig mit dem timer?

Code: Alles auswählen

if(Dummy_alle_geschlossen.state == ON)
    return;
val Integer iMonth = now.getMonthValue 

if(iMonth > 3 && iMonth < 10)
createTimer(now.plusMinutes(60), [|              
    Rolladen.members.forEach[ r | 
        r.sendCommand(DOWN)
        Thread::sleep(900)
  ]]) 
 else
    Rollladen_Winter.members.forEach[ r |
        r.sendCommand(DOWN)
        Thread::sleep(900)
    ]
Dummy_alle_geschlossen.postUpdate(ON)
Oli
Konfig: OpenHab 3.3.0 auf Raspi 4B+ (Raspian).
SomfyTahoma-Bridge im LAN-Modus, Brunnen-, Zisternensteuerung, Außenlampen, Heizung (WebKM200), PV-Anlage per MQQT, Miele-Trockner, Softliq SC18, Dreambox two sowie div. Shellys zur Steckdosensteuerung per Openhab vernetzt.
Visualisierung über Grafana. Daten in Influx gesichert.

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

Re: Wo ist der Fehler in meiner Rule?

Beitrag von udo1toni »

Ja, aber besser ist es, den Code (mindestens in der Testphase) ordentlich einzurücken:

Code: Alles auswählen

if(Dummy_alle_geschlossen.state == ON)
    return;
val Integer iMonth = now.getMonthValue 

if(iMonth > 3 && iMonth < 10)
    createTimer(now.plusMinutes(60), [|
        Rolladen.members.forEach[ r | 
            r.sendCommand(DOWN)
            Thread::sleep(900)
        ]
    ])
else
    Rollladen_Winter.members.forEach[ r |
        r.sendCommand(DOWN)
        Thread::sleep(900)
    ]
Dummy_alle_geschlossen.postUpdate(ON)
Einfach um zu erkennen, dass die erste schließende eckige Klammer zum Lambda des forEach gehört, während die zweite eckige Klammer zum Lambda des createTimer gehört (so wie auch die folgende schließend runde Klammer).
Man könnte den Code auch in eine einzige Zeile schreiben, mit jeweils einem Leerzeichen statt Zeilenumbruch, aber in dieser Form ist es doch wesentlich besser lesbar.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Grandlhuber
Beiträge: 26
Registriert: 22. Sep 2021 07:38
Answers: 0
Wohnort: Bamberg

Re: Wo ist der Fehler in meiner Rule?

Beitrag von Grandlhuber »

Ok danke.

Habe ich die Klammern richtig verstanden (Habe sie der meiner Meinung nach in richtiger Reihenfolge eingefärbt):?

if(Dummy_alle_geschlossen.state == ON)
return;
val Integer iMonth = now.getMonthValue

if(iMonth > 3 && iMonth < 10)
createTimer(now.plusMinutes(60), [|
Rolladen.members.forEach[ r |
r.sendCommand(DOWN)
Thread::sleep(900)
]
])


else
Rollladen_Winter.members.forEach[ r |
r.sendCommand(DOWN)
Thread::sleep(900)
]
Dummy_alle_geschlossen.postUpdate(ON)
Konnte hier die Codeansicht mit dem Einrücken nicht aktivieren, da sonst die Einfärbungen weg wären :shock:

Kurz Frage: Was hat es eigentlich mit diesem " | " (ohne Gänsefüßchen) auf sich? Ist das dein angedeuteter Zeilenumbruch für den Code wie z.B. in VBA ( "& _")?

Oli
Konfig: OpenHab 3.3.0 auf Raspi 4B+ (Raspian).
SomfyTahoma-Bridge im LAN-Modus, Brunnen-, Zisternensteuerung, Außenlampen, Heizung (WebKM200), PV-Anlage per MQQT, Miele-Trockner, Softliq SC18, Dreambox two sowie div. Shellys zur Steckdosensteuerung per Openhab vernetzt.
Visualisierung über Grafana. Daten in Influx gesichert.

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

Re: Wo ist der Fehler in meiner Rule?

Beitrag von udo1toni »

Das ist nicht die Code-Ansicht, sondern ein Zitat. Innerhalb des Codes kannst Du hier keine Auszeichnungen vornehmen, da sie per Definition Bestandteil des Codes sind. Aber ja, die farbliche Zuordnung passt so.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten