Rule läuft manchmal nicht !

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Baumtasche
Beiträge: 82
Registriert: 14. Sep 2020 21:52
Answers: 0

Rule läuft manchmal nicht !

Beitrag von Baumtasche »

Hallo zusammen,

ich bin noch relativ neu in der Materie Openhab, deswegen kann es sein, dass meine Frage für euch vielleicht lächerlich ist.
Ich habe seid Tagen ein Problem das ich nicht lösen kann. Ich habe eine Rule die vom Lichtwert eines Lichtsensors ausgelöst wird. Diese funktioniert aber komischerweise nur, wenn ich kurz vorher eine Änderung und wenn sich auch noch so unbedeutend ist (z.B. Kommentar einfügen) vornehme.
Konkret sieht das so aus. Die Helligkeit fällt unter 10, es passiert nichts, ich nehme eine Änderung vor, und bei nächsten Zyklus, wo der Lichtsensor erneut eine Helligkeit unter 10 misst, funktioniert die rule :cry: .
Um einen Zufall auszuschließen habe ich das jetzt über 3 Tage beobachtet und getestet.

Wenn man eine Änderung in der Rule vornimmt dann erscheint im LOG

19:07:58.942 [INFO ] [del.core.internal.ModelRepositoryImpl] - Loading model 'Rollo.rules'
19:08:07.755 [INFO ] [del.core.internal.ModelRepositoryImpl] - Refreshing model 'Rollo.rules'

Sieht fast so aus, dass durch die Änderung erst die rule geladen wird und deswegen dann funktioniert.
Ich habe auch berücksichtigt das Openhab nur 5 rules gleichzeitig bearbeiten kann, aber ich aber nur zwei rules, die auf den Lichtsensor reagieren, also daran kann es auch nicht liegen, oder?
Ich hoffe einer von euch, hat einen guten Tipp für mich , ich verzweifle schon :oops:



Anbei ein Auszug aus der rule

Code: Alles auswählen


rule "React on Aktuelle Helligkeit (Lichtsensor_1_CurrentIllumination) change/update"

when
   Item Lichtsensor_Aussen changed 
then
    if((Lichtsensor_Aussen.state as Number)  < 10)  { 
            Rollo_Bad_Level.sendCommand(100)
            Thread::sleep(15000)
            Rollo_SchlafzKleider_Level.sendCommand(100)
            Thread::sleep(7000) 
            Rollo_SchlafzGarage_Level.sendCommand(100)
            Thread::sleep(2000)
            Rollo_SchlafzBalkon_Level.sendCommand(32)
            Thread::sleep(3000)
......

Benutzeravatar
peter-pan
Beiträge: 2767
Registriert: 28. Nov 2018 12:03
Answers: 30
Wohnort: Schwäbisch Gmünd

Re: Rule läuft manchmal nicht !

Beitrag von peter-pan »

...also mal abgesehen davon, dass das mit dem "Thread::sleep(xxxx)" suboptimal ist, bist du dir sicher, dass der Vergleich richtig ist ? Wie sieht denn das Item aus ?

Vielleicht hilft:

Code: Alles auswählen

if((Lichtsensor_Aussen.state as Number).floatValue  < 10)
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.3.5 openhabian

Baumtasche
Beiträge: 82
Registriert: 14. Sep 2020 21:52
Answers: 0

Re: Rule läuft manchmal nicht !

Beitrag von Baumtasche »

ja, ich bin mir sicher da sie eigentlich funktioniert, sobald ich eine Änderung mache, auch wenn ich die Änderung wieder zurücknehme. Es sieht so aus, das durch die Änderung die rule bei Openhab erst bekannt wird.
Zum besseren Verständnis, wenn die Helligkeit z.B auf 9 fällt, passiert nichts, ich mache eine Änderung, die Helligkeit fällt weiter auf 8 und dann funktioniert es :cry:

Warum ist das mit dem Thread::sleep(xxxx) suboptimal? Ich will nicht das alle Rollos gleichzeitig runtergehen, sie sollen versetzt runtergehen, gibt es da eine bessere Lösung?

Benutzeravatar
peter-pan
Beiträge: 2767
Registriert: 28. Nov 2018 12:03
Answers: 30
Wohnort: Schwäbisch Gmünd

Re: Rule läuft manchmal nicht !

Beitrag von peter-pan »

Das geht mit einem Timer sicher besser, da kann dir vielleicht @udo1toni einiges dazu sagen bzw. du suchst hier mal im Forum nach "createTimer".
Baumtasche hat geschrieben: 1. Okt 2020 22:04 ja, ich bin mir sicher da sie eigentlich funktioniert
Das kann man nun so oder so sehen, denn eigentlich funktioniert sie ja nicht ;)
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.3.5 openhabian

hannahgrf
Beiträge: 10
Registriert: 1. Okt 2020 18:23
Answers: 0

Re: Rule läuft manchmal nicht !

Beitrag von hannahgrf »

Wie du ja schon gesagt hast, kann openHAB nur 5 parallel bearbeiten. Um nun die Lichteinstellung zu ändern, brauchst du einen Timer. Den stellst du mit time cron + create timer ein. Anschließend gibst du die Bedingungen für den Timer ein.

Benutzeravatar
OliverCJ
Beiträge: 405
Registriert: 29. Aug 2017 12:41
Answers: 3
Wohnort: Bergisch Gladbach

Re: Rule läuft manchmal nicht !

Beitrag von OliverCJ »

Nur mal so als Idee (auch wenn Du das nicht möchtest): Lass doch mal die Thread:sleep weg. Dann gehen halt mal alle Rollos gleichzeitig runter. Aber dann weißt Du zumindest, ob die Rule ansonsten so funktioniert wie sie soll. Kannst du nachher immer noch wieder einbauen,
Außerdem wäre es wahrscheinlich hilfreich, die Rule tatsächlich komplett zu posten und nicht mit "..." den weiteren Verlauf anzudeuten. Könnte ja sein, dass in dem weggelassenen Teil noch ein Fehler ist...

_______________________________________________
Homematic IP Komponenten an CCU 3 (wächst stetig)
Innogy Smarthome System (verabschiedet sich langsam)
Philips Hue Beleuchtung
Fritz!Box
VU+ Solo SAT-Receiver
2 Squeezeboxen
Denon Heos System

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

Re: Rule läuft manchmal nicht !

Beitrag von udo1toni »

Also, die Rule ist ja nun nicht vollständig, insofern ist die Schwere Deines Vergehens nicht abschätzbar ;) aber Deine Aussage, dass Du ja "nur zwei Rules" hast, welche auf das Item Lichtsensor_Aussen reagieren, und deshalb könnte die grenze von fünf gleichzeitig laufenden Rules nicht überschritten sein, zeigt, dass Du noch nicht vollständig verstanden hast, wie openHAB funktioniert.

Eine Rule (eine!) kann theoretisch hunderte Male gleichzeitig ausgeführt werden, wenn sie nur oft genug getriggert wird und lang genug läuft (und man die Anzahl gleichzeitig ausführbarer Rules entsprechend hochgesetzt hat - tu das nicht!)
Die Threads beziehen sich auf alle Rules insgesamt. Wenn Du also viele Rules hast, die ähnlich gegen die grundsätzlichen Regeln der Programmierung verstoßen wie der Teil der gezeigten Rule, ist es im Gegenteil sogar sehr wahrscheinlich, dass Deine Rules sich gegenseitig blockieren.

Der erste Punkt ist, dass man es grundsätzlich vermeiden sollte, Rules zu definieren, die identische Trigger aufweisen. Es gibt nur wenige Situationen, in denen das ok ist, und man sollte genau überlegen, ob die Rule Engine sich dann tatsächlich immer korrekt verhalten wird (z.B. welche der Rules wurde als erstes gestartet).

Der zweite Punkt ist die Sache mit dem Thread::sleep(). Es ist eine ganz schlechte Idee, Rules zu schreiben, die wesentlich länger als einige hundert Millisekunden(!) laufen.
Was die konkrete Steuerung der Rollläden betrifft: Gibt es wichtige Gründe, ganz bestimmte Abstände zwischen den einzelnen Rollladenfahrten zu verwenden? Ein automatisches Schließen ist sicherlich ok, auch dass bestimmte Läden auf eine Lüftungsposition gefahren werden, aber das macht es natürlich etwas schwerer, die Rule effizient zu gestalten. Aber mal als Beispiel:

Code: Alles auswählen

// globale Variablen zu Beginn der Datei definieren!
var Timer tShutter = null
var Integer iShutter = 0

rule "Rollläden schließen"
when
    Item Lichtsensor_Aussen changed
then
    if(tShutter !== null) {                                                                                  // Timer läuft schon
        logInfo("shutter","Rule getriggert, aber Timer bereits aktiv. Abbruch!")
        return;
    }
    if(!(Lichtsensor_Aussen.state instanceof Number)) {                                                      // ist der Status eine Zahl?
        logWarn("shutter","Lichtsensor liefert ungültigen Status ({}). Abbruch!",Lichtsensor_Aussen.state)
        return;
    }
    val Number nPrev = if(previousState instanceof Number) (previousState as Number).floatValue else 20      // alten Wert auslesen
    if((Lichtsensor_Aussen.state as Number).floatValue < 10 && nPrev > 10) {                                 // Falls Schwellwert unterschritten und vorher nicht unterschritten
        iShutter = 0                                                                                         // Zähler zurücksetzen
        tShutter = createTimer(now.plusMillis(10),[|                                                         // Timer anlegen und starten
            iShutter = iShutter + 1                                                                          // Zähler erhöhen
            switch(iShutter) {                                                                               // Abhängig vom Zähler
                case 1: {                                                                                    // 1. Schritt
                    Rollo_Bad_Level.sendCommand(100)
                    tShutter.reschedule(now.plusSeconds(15))                                                 // Timer erneut ausführen in 15 Sekunden
                }
                case 2: {                                                                                    // 2. Schritt
                    Rollo_SchlafzKleider_Level.sendCommand(100)
                    tShutter.reschedule(now.plusSeconds(7))
                }
                case 3: {                                                                                    // 3. Schritt
                    Rollo_SchlafzGarage_Level.sendCommand(100)
                    tShutter.reschedule(now.plusSeconds(2))
                }
                case 4: {                                                                                    // 4. Schritt
                    Rollo_SchlafzBalkon_Level.sendCommand(32)
                    tShutter.reschedule(now.plusSeconds(3))
                }
                case 5: ...                                                                                  // 5. Schritt
                default: {                                                                                   // letzter Schritt
                    tShutter = null
                }
            }
        ])
    }
end
Allein die große Menge an gleichartigen Befehlen sieht nicht schön aus. Gegenbeispiel:

Code: Alles auswählen

// globale Variablen zu Beginn der Datei definieren!
var Timer tShutter = null
var Integer iShutter = 0

val lShutter      = newArrayList('Bad', 'SchlafzKleider', 'SchlafzGarage', 'SchlafzBalkon')
val lShutterClose = newArrayList(100, 100, 100, 32)
val lShutterTime  = newArrayList(15, 7, 2, 3)


rule "Rollläden schließen"
when
    Item Lichtsensor_Aussen changed
then
    if(tShutter !== null) {                                                                                  // Timer läuft schon
        logInfo("shutter","Rule getriggert, aber Timer bereits aktiv. Abbruch!")
        return;
    }
    if(!(Lichtsensor_Aussen.state instanceof Number)) {                                                      // ist der Status eine Zahl?
        logWarn("shutter","Lichtsensor liefert ungültigen Status ({}). Abbruch!",Lichtsensor_Aussen.state)
        return;
    }
    val Number nPrev = if(previousState instanceof Number) (previousState as Number).floatValue else 20      // alten Wert auslesen
    if((Lichtsensor_Aussen.state as Number).floatValue < 10 && nPrev > 10) {                                 // Falls Schwellwert unterschritten und vorher nicht unterschritten
        iShutter = 0                                                                                         // Zähler zurücksetzen
        tShutter = createTimer(now.plusMillis(10),[|                                                         // Timer anlegen und starten
            if(lShutter.size >= iShutter) {
                tShutter = 0
                return;
            }
            sendCommand("Rollo_" + lShutter(iShutter) + "_Level",lShutterClose(iShutter).intValue)           // Shutternamen aus Liste berechnen und mit passendem Wert ansteuern
            tShutter.reschedule(now.plusSeconds(lShutterTime(iShutter).intValue))                            // Timer erneut planen
            iShutter = iShutter + 1                                                                          // Zähler erhöhen
        ])
    }
end
Hier werden die Namen, Sollhöhen und Wartezeiten aus drei Listen entnommen. Wird das Ende der Liste erreicht, stoppt der Timer.
Ich setze hier voraus, dass alle Rollläden dem Namensschema folgen. Auch wenn die Variante mit der Arraylist nicht optimal ist, kann man sehr schön sehen, dass der Code wesentlich effizienter ist. Die Rule wird nicht länger, egal, wie viele Rollläden auch in der Liste eingetragen sein mögen.

Das Wichtigste bei der Rule ist aber, sicherzustellen, dass der Code nur einmalig gestartet wird. das macht den weitaus größeren Teil der Rule aus :)
Der Timer sorgt dafür, dass die Threads minimal belegt sind - wenige Millisekunden bei Wertänderung des Sensors, wenige Millisekunden wenn ein Rollladen angesteuert wird.
openHAB4.3.5 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

Baumtasche
Beiträge: 82
Registriert: 14. Sep 2020 21:52
Answers: 0

Re: Rule läuft manchmal nicht !

Beitrag von Baumtasche »

Wow, ihr seid echt Klasse, vielen vielen Dank für eure Hilfe, insbesondere an udo1toni. Ist der Wahnsinn, was du du für Zeit investiert hast, mir als Anfänger, das so ausführlich zu erklären. Den Code dazu hast du auch gleich mitgeliefert. DAAAAAANNNKE
Ich werde berichten, ob es funktioniert hat.

Baumtasche
Beiträge: 82
Registriert: 14. Sep 2020 21:52
Answers: 0

Re: Rule läuft manchmal nicht !

Beitrag von Baumtasche »

Nachtrag: anbei der komplette ursprüngliche Code

Code: Alles auswählen


rule  "Aktuelle Helligkeit fällt unter 10" //"React on Aktuelle Helligkeit (Lichtsensor_1_CurrentIllumination) change/update"

when
   Item Lichtsensor_Aussen changed 
then
    if((Lichtsensor_Aussen.state as Number)  < 30 && (ItemRollo_Geschlossen== CLOSED)) { 
            Rollo_Bad_Level.sendCommand(100)
            Thread::sleep(8000)
            Rollo_SchlafzKleider_Level.sendCommand(100)
            Thread::sleep(7000) 
            Rollo_SchlafzGarage_Level.sendCommand(100)
            Thread::sleep(2000)
            Rollo_SchlafzBalkon_Level.sendCommand(32)
            Thread::sleep(3000)
            Rollo_KindLinks_Level.sendCommand(63)
            Thread::sleep(1000)
            Rollo_KindRechts_Level.sendCommand(100)
            Thread::sleep(1500)
            Rolle_Kueche_Level.sendCommand(100)
            Thread::sleep(3000)
            Rollo_Wohnzimmer_Level.sendCommand(100)
        
            if(DrehTerrasse_State == CLOSED)
                Rollo_Terrasse_Level.sendCommand(32)       
      
            ItemRollo_Geschlossen.postUpdate(ON)
        }
    
end



Baumtasche
Beiträge: 82
Registriert: 14. Sep 2020 21:52
Answers: 0

Re: Rule läuft manchmal nicht !

Beitrag von Baumtasche »

Hallo Udo1toni,

kannst du bitte noch Mal auf folgende Passage von dir schauen?

Code: Alles auswählen

            sendCommand("Rollo_" + lShutter(iShutter) + "_Level",lShutterClose(iShutter).intValue)           
            tShutter.reschedule(now.plusSeconds(lShutterTime(iShutter).intValue))                            
            iShutter = iShutter + 1                                                                          
        ])
VSCode meldet, dass lShutter --> invalid number of arguments. The field lShutter is not applicable for the arguments (Integer), dass gleiche bei lShutterClose

Antworten