Seite 1 von 2

Schaltzeit Item

Verfasst: 3. Mär 2023 15:20
von Wolle17
Hallo Zusammen,

Ich habe mich nun das erste mal an eine etwas komplexere (für meine Verhältnisse) Regel probiert.
Ich möchte mir gerne anzeigen lassen wie lange bestimmte Items geschaltet sind.

Code: Alles auswählen

 var Long       lStart = 0                                    
var Integer  iSeconds = 0                                   
var Timer      tBadlicht = null                                

rule "Badlicht"
when
    Time cron "5 0 0 * * ?"                                 
then
    iSeconds = 0                                            
end

rule "detect switching"

when
    Item Badlicht changed
then
    if(newState == O} 
    lStart = now.ofEpochSeconds                      
    } else {                                                
        iSeconds += (now.toEpochSeconds - lStart).intValue
    }
end
Passt die Regel so?
Jetzt steh ich aber noch vor dem Problem dass ich nicht weiß wie ich mir den Wert in einem Item anzeigen lassen kann.

Könnte mich da jemand unterstützen?

Danke sehr!

Re: Schaltzeit Item

Verfasst: 3. Mär 2023 17:41
von udo1toni
Einmal .ofEpochSeconds, einmal .toEpochSeconds :) das kann nicht so ganz stimmen.
Im Prinzip sollte es aber soweit passen, sofern Du die Einschaltdauer pro Tag wissen willst. Der Reset um 00:00:05 Uhr führt natürlich dazu, dass, falls zu dem Zeitpunkt das Badlicht gerade an ist, noch der Anteil der Einschaltzeit vom vorigen Tag mit gezählt wird. (muss man nur wissen, nicht dass man sich dann wundert, warum und 00:00:06 beim Ausschalten eine Einschaltdauer von 1 Stunde angezeigt wird (ausgiebiges Bad, welches zufällig um 23 Uhr begann und kurz nach 0 Uhr endete...)

Um den Wert angezeigt zu bekommen, musst Du ihn noch in einem Item speichern, über MeinItem.postUpdate(iSeconds).
Falls Du den Wert lieber nicht Sekunden sehen willst, hast Du die Wahl der Qual...

Re: Schaltzeit Item

Verfasst: 7. Mär 2023 14:34
von Wolle17
Danke dir Udo,

Bin leider erst jetzt zum probieren gekommen,
es funktioniert noch nicht so recht, hab mal wieder ne blöde Frage, wie genau wäre der Code zum speichern im Item und welches Item muss es sein, ich hatte ein Number:Time Item genommen.

Danke vorab :-)

Re: Schaltzeit Item

Verfasst: 7. Mär 2023 17:58
von udo1toni
Im Item speicherst Du den Wert mit .postUpdate()

Ich hatte allerdings irgendwie schief geschaut... da sind dann neben dem of und to... noch ein, zwei Punkte...

Code: Alles auswählen

var Long        lStart = 0
var Integer   iSeconds = 0
var Timer    tBadlicht = null

rule "täglicher Zähler Reset"
when
    Time cron "5 0 0 * * ?"
then
    iSeconds = 0
end

rule "Badlicht geschaltet"
when
    Item Badlicht changed
then
    if(newState == ON}
        lStart = now.toInstant.toEpochMilli
    } else {
        iSeconds += ((now.toInstant.toEpochMilli - lStart)/1000).intValue
        MeinNumberItem.postUpdate(iSeconds)
    }
end
Da ich weder ofEpochSeconds noch toEpochSeconds kenne (also, es gibt beide... aber ich kenne sie halt nicht), nehme ich toEpochMilli, das setze ich selbst ein. Steht aber nur für die instanzierte Version von now zur Verfügung, deshalb das .toInstant

Du hast oben in Deinem Code noch den Tippfehler, dass Du auf newState == O testest, das ist natürlich kein gültiger Status :)

Re: Schaltzeit Item

Verfasst: 7. Mär 2023 21:27
von Wolle17
Ich Trau mich schon garnicht mehr zu schrieben.

Leider zeigt mein Item (Number:Time) keinen Wert sondern nur NULL an, wo kann der Fehler sein?

Habt bitte Geduld mit mir 😅

Re: Schaltzeit Item

Verfasst: 8. Mär 2023 07:40
von udo1toni
Gibt es im Log Meldungen?

Re: Schaltzeit Item

Verfasst: 8. Mär 2023 10:09
von Wolle17
Leider kann ich mir die Log Meldungen nicht so schön anzeigen lassen (Windows) hab mit aber mal im Ordner Logs die letzte Datei angeschaut und da sind keine Logs der Rule zu sehen.
Mal wieder eine dumme Frage… müsste nicht wenn ich das BadLicht einschalte der Status von IDLE zu RUNNING wechseln?

Re: Schaltzeit Item

Verfasst: 8. Mär 2023 10:59
von udo1toni
Nein, nicht wechseln, es könnte allenfalls sein, dass es kurz "aufblitzt". Die Rule wird pro Schaltvorgang nur wenige Millisekunden laufen, typisch würde ich von etwa 3 bis 5 Millisekunden ausgehen.

Du kannst die Rule gezielt mit Logmeldungen ergänzen.
Vorher aber die Frage (Wenn Du von der UI im Zusammenhang mit den Rules sprichst): Du hast die Rule aber schon über eine Textdatei im Ordner \rules\ angelegt? Falls nicht, müssten die Rules geändert werden, zum Einen stimmt dann das Format nicht, zum Anderen kannst Du dann keine globalen Variablen verwenden.

Re: Schaltzeit Item

Verfasst: 8. Mär 2023 12:44
von Wolle17
Ich hab sie in der UI unter Scripts - Rule DSL erstellt!? 🙈

Re: Schaltzeit Item

Verfasst: 9. Mär 2023 07:30
von udo1toni
Nein, das geht nicht, jedenfalls nicht so.

Zwei Möglichkeiten:

1. Du kopierst beiden Rules komplett so, wie sie sind in eine Textdatei und speicherst diese im Konfigurationsverzeichnis in dem Verzeichnis rules\ ab, der Dateiname muss als Endung zwingend .rules lauten, was davor steht, ist im Prinzip egal, aber ich würde es nicht ausreizen wollen. Am besten nimmst Du was einfaches, z.B. einschaltdauer.rules (man beachte die Kleinbuchstaben - möglichst einfach). In der UI entfernst Du die Rules restlos.
Die beiden Rules sollten umgehend in der UI unter den Rules gelistet werden.

2. Du änderst die Rules passend ab, so dass sie für die UI korrekt sind. Wichtig dabei: es handelt sich um zwei Rules. Der Teil zwischen when und then muss in der UI als when-Teil eingetragn werden, der Teil zwischen then und end kommt als Code in die Action der Rule. Ein Problem, um was wir uns dann noch kümmern müssen, ist die globale Variable, bzw. man wird das Problem dann anders lösen.
Nehmen wir an (Du hast den Namen leider bisher nicht erwähnt), Dein Number:Time Item heißt BadlichtED (für EinschaltDauer). Die erste Rule (hier als Code-Ansicht in der UI):

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      time: 00:00:01
    type: timer.TimeOfDayTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: BadlichtED.postUpdate(0)
    type: script.ScriptAction
Diese Rule triggert eine Sekunde nach 0 Uhr und setzt das Item BadlichtED auf 0. Alternativ kannst Du als Trigger auch Time cron angeben, aber über TimeOfDay ist es ebenfalls super einfach. Du könntest bei dieser Rule auch auf den Code komplett verzichten und stattdessen einfach direkt dem Item den Wert 0 zuweisen (es gibt dafür eine eigene Action)

Die zweite Rule:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: NEGBadLicht
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: if(newState == OFF) {
            var Integer iSeconds = BadlichtED.state as Number
            val bis = Badlicht.previousState(false).timestamp.zonedDateTime.toInstant.toEpochMilli
            val von = Badlicht.previousState(true).timestamp.zonedDateTime.toInstant.toEpochMilli
            val dauer = ((bis - von)/1000).intValue
            iSeconds += dauer
            BadlichtED.poistUpdate(iSeconds)
        }
    type: script.ScriptAction
Die Rule liest nun die Zeitstempel aus, zu denen die letzten Änderungen des Status stattgefunden haben. false nimmt dabei das letzte Update, true nimmt das letzte Update, bei dem ein Wechsel stattgefunden hat.
Eventuell vertue ich mich dabei gerade... Es gibt aber weiter Möglichkeiten, zum "vorletzten" Statuswechsel zu kommen, probiere erst mal diese Variante (nur für den Fall, dass Du keine Textdateien verwenden willst... die Rules oben werden sicher funktionieren).
In der UI gibt es meines Wissens für die DSL noch keine Möglichkeit, Werte über den Lauf der Rule hinaus aufzubewahren. Man könnte höchstens ein Number Item dafür verwenden. Aber theoretisch müsste es über die Persistence Daten ebenso gehen, ganz ohne Hilfsvariablen.