Seite 1 von 1

sorry, regel, cron

Verfasst: 9. Jun 2024 22:55
von steinadler
hier mal meine ganze regel in openhab die funktioniert(erstmal)

Code: Alles auswählen

rule "zurück"
when
//Time cron "0/5 * * ? * MON-SUN *"
Time cron "0 0 0 ? * MON-SUN *"
then
val dayOfWeek = now.getDayOfWeek.getValue()
val dezimalzahl = 0.0
switch (dayOfWeek) {
case 1: Montag.postUpdate(dezimalzahl)
case 2: Dienstag.postUpdate(dezimalzahl)
case 3: Mittwoch.postUpdate(dezimalzahl)
case 4: Donnerstag.postUpdate(dezimalzahl)
case 5: Freitag.postUpdate(dezimalzahl)
case 6: Sonnabend.postUpdate(dezimalzahl)
case 7: Sonntag.postUpdate(dezimalzahl)
}
end





rule "setzen"
  when
   Item RegenM changed
  then
   val wochentag = now.getDayOfWeek.getValue()
   val dezimalzahl = (Regenzaehler.state as Number + 0.0).doubleValue()
    switch (wochentag) {
     case 1: Montag.postUpdate(dezimalzahl)
     case 2: Dienstag.postUpdate(dezimalzahl)
     case 3: Mittwoch.postUpdate(dezimalzahl)
     case 4: Donnerstag.postUpdate(dezimalzahl)
     case 5: Freitag.postUpdate(dezimalzahl)
     case 6: Sonnabend.postUpdate(dezimalzahl)
     case 7: Sonntag.postUpdate(dezimalzahl)
   }
end 

nun zu meiner frage
ich wollte den regenmesser jeden tag,der auch aktuelle ist,( und nur der) um null uhr auf null setzen
die werte der anderen tage sollen erhalten bleiben, bis der tag abricht( der wochentag) der auch auf null gesetzt wird
also wenn montag anbricht auf null, dann weiter zählen was an regen fällt
wenn dienstag anbricht, dann weiterzählen was an regen fällt.....

warummuss ich zwei verschiedene wege gehen um den wochentag, der gerade aktuell ist, um dem item-wochentag zu manipulieren

die regel läuft
1.
when
//Time cron "0/5 * * ? * MON-SUN *"
Time cron "0 0 0 ? * MON-SUN *"
then................
2.when
Item RegenM changed
then
val wochentag = now.getDayOfWeek.getValue()
val dezimalzahl = (Regenzaehler.state as Number + 0.0).doubleValue()..........
wie gesagt, warum funktioniert der zweite regelaufruf(wenn ich ihn umgebaut habe) nicht so wenn ich ihn in der ersten einfüge...

mir geht es nur um die auswahl und zuweisung des entsprechenden wochentages
das war jetzt sehr kompliziert auszudrücken, hoffentlich gehts gut, wie gesagt die regel funktioniert so, nur so, aber warum ???
danke schonmal im vorraus

Re: sorry, regel, cron

Verfasst: 9. Jun 2024 23:13
von udo1toni
Zunächst einmal ist Dein Trigger zum Löschen unnötig kompliziert.
Und es wäre geschickter, die Itemnamen etwas anders zu gestalten. .getDayOfWeek liefert als Wert Monday, bis Sunday, es wäre also sinnvoll, die Items auch so zu benennen. Oder noch besser, da es ja um Niederschlagsmengen geht, bennenne sie z.B. Rain_Monday bis Rain_Sunday. Packe alle diese Items in eine gemeinsame Gruppe gRain, dann sieht die Rule zum Löschen so aus:

Code: Alles auswählen

rule "RegenTag rücksetzen"
when
Time cron "0 0 0 * * ?" // täglich um 0 Uhr
then
    gRain.members.filter[i|i.name.endsWith(now.getDayOfWeek)].head.postUpdate(0.0)
end
Und die Rule zum aktualisieren des Wertes wäre ebenfalls einfacher:

Code: Alles auswählen

rule "RegenTag setzen"
when
   Item Regenzaehler changed
then
    val fMenge = if(newState instanceof Number) (newState as Number).floatValue else 0
    gRain.members.filter[i|i.name.endsWith(now.getDayOfWeek)].head.postUpdate(fMenge)
end 
Warum Du die Rule auf RegenM trigern lässt, dann in der Rule aber Regenzaehler verwendest, ist mir nicht klar, sinnvoller wäre es jedenfalls, das Item mit dem konkreten Wert als Trigger mit changed zu verwenden, denn dann enthält die implizite Variable newState den neuen Status des Items (wie im Code zu sehen)

Re: sorry, regel, cron

Verfasst: 9. Jun 2024 23:40
von steinadler
danke ersteinmal
aber dachte das now.getDayOfWeek nur eine (zahl) zurück gibt , zb. montag=1, demnach dürfte es egal sein was ich nach dieser 1= benenne
RegM ist mein virtueller schalter, den ich auch eben zum ausprobieren hin und her schieben kann(es regnet ja nicht immer), klaro, wenn alles läuft werde ich den schalter weg machen, aber bis dahin ist er mir eine hilfe zum ausprobieren
vielen dank deiner hilfe und deinen hinweisen
entschuldige, habe dir meine erste regel vorenthalten

Code: Alles auswählen

rule "Regenmesser"
when
    Item RegenM changed
then
    if (RegenM.state == ON) {
        // Zustand ist jetzt ON
        if (Regenzaehler.state == NULL) {
            Regenzaehler.postUpdate(0.0)
        } else {
            Regenzaehler.postUpdate(Regenzaehler.state as Number + 0.667)
        }
    } else {
        // Zustand ist jetzt OFF
        if (Regenzaehler.state == NULL) {
            Regenzaehler.postUpdate(0.667)
        } else {
            Regenzaehler.postUpdate(Regenzaehler.state as Number + 0.667)
        }
    }
    if (RegenResett.state == ON) {
        Regenzaehler.postUpdate(0) // Setze den Wert des Regenmengenzählers auf null
       
    
       (RegenResett.postUpdate(OFF))
         //Therd :: sleep (100)
    }
    end  
    
das ist mein Anfang, darauf habe ich ausprobiert und geschrieben....

Re: sorry, regel, cron

Verfasst: 10. Jun 2024 05:46
von udo1toni
steinadler hat geschrieben: 9. Jun 2024 23:40 dachte das now.getDayOfWeek nur eine (zahl) zurück gibt
:) deshalb braucht es ja noch das .getValue, weil .getDayOfWeek eben keine Zahl mehr liefert - mit joda Time war das noch so, mit JavaTime ist ads Verhalten aber anders.
steinadler hat geschrieben: 9. Jun 2024 23:40 RegM ist mein virtueller schalter, den ich auch eben zum ausprobieren hin und her schieben kann
Ah, ja, ok, dann kannst Du natürlich (solange Du den Schalter verwendest) nicht newState verwenden, sondern musst den Status des Items auslesen.

Gegenangebot für die Rule:

Code: Alles auswählen

rule "Regenmesser"
when
    Item RegenM changed                                         // Schalter betätigt
then
    var Number nRegen = 0.0                                     // Variable initialisieren

    if(RegenResett.state == ON)                                 // Falls Reset aktiv
       RegenResett.postUpdate(OFF)                              // deaktivieren
    else {                                                      // ansonsten
        if(Regenzaehler.state instanceof Number)                // falls gültiger Wert
            nRegen = (Regenzaehler.state as Number).floatValue  // Wert holen
        nRegen += 0.667                                         // und Wert erhöhen
    }
    if(Regenzaehler.state.toString != nRegen.toString)          // falls aktueller Wert abweicht
        Regenzaehler.postUpdate(nRegen)                         // Wert zurückschreiben
end
Der Ausdruck Regenzaehler.state as Number kann eine NullPointer Exeption auslösen, falls Regenzaehler.state keine gültige Zahl liefert. Du fragst in Deinem Code NULL als Status ab. Das ist aber nur die halbe Wahrheit, denn der Status kann mindestens noch UNDEF annehmen. Deshalb ist die Prüfung auf instanceof Number besser.
Weiterhin könnte Regenzaehler.state z.B. auch 1.2 mm als Wert liefern, wenn das Item als Number:Length definiert wäre (was für einen Regensensor eigentlich ganz geschickt wäre...). Dummerweise wird dann aber die Berechnung schief gehen. Das hängt damit zusammen, dass 0.667 keine Einheit mitliefert. Es ist also sinnvoll, den Ausdruck Regenzaehler.state as Number explizit nach Float zu wandeln.
Außerdem sollte das Casting Item.state as Number immer geklammert werden, die Berechnung kann sonst gerne mal schief gehen.

Durch dIe geänderte Reihenfolge der Anweisungen kann man sich außerdem unnötige Doppelungen im Code ersparen :)

Das letzte if() sorgt dafür, dass der Regenzähler nur dann gesetzt wird, wenn dieser nicht ohnehin den aktuellen Wert enthält.
Wenn der Wert erhöht wird, kann der Wert nicht der gleiche sein :) das ist also hier nur für den Fall interessant, dass das Item mehrfach hintereinander "genullt" wird.