Seite 1 von 2

[GELÖST] Stoppuhr

Verfasst: 30. Okt 2022 21:08
von lenschith
Hallo zusammen,
ich möchte gerne eine Stoppuhr, die aktiviert wird wenn ein Gerät z.B. Waschmaschine startet und die Zeit stopp wenn das Gerät wieder aus ist. Ich habe leider nichts passendes gefunden. Gibt es da eine Möglichkeit die Werte zu ermitteln?

Danke Gruß
Lenschi

Re: Stoppuhr

Verfasst: 31. Okt 2022 00:16
von udo1toni
ja, das ist kein Problem. Du musst Dir einfach beim Start den Zeitpunkt merken und beim Stoppen die Differenz bestimmen. :)

Das geht so:

Code: Alles auswählen

var Long lStart = 0
var Integer iSeconds = 0

rule "Betriebsdauer messen"
when
    Item Waschmaschine changed
then
    if(newState == ON) {
        lStart = now.toInstant.toEpochMilli
    } else {
        iSeconds = ((now.toInstant.toEpochMilli - lStart)/1000).intValue
        logInfo("Dauer", "Gemessene Dauer in Sekunden: {}",iSeconds)
    }
end

Re: Stoppuhr

Verfasst: 1. Nov 2022 11:28
von lenschith
Hallo Udo,

irgendwie klappt das nicht bei mir. Aber nach langer Überlegung und Testes bin ich zu Erkenntnis gekommen das ich eigentlich was anderes für mein Vorhaben benötige. Ich möchte wenn ein Item auf ON ist eine Uhr laufen lassen die alle 60 Sekunden ein Item mit der aktuellen Laufzeit in HH:MM:SS befüllt um zu sehen wie lange das Gerät bereits läuft. Wenn das Item wieder auf OFF geht sollte die Zeit wieder resettet werden auf 00:00:00 werden. Ich habe gestern Stunden mit Blockly und ECMA Scripte verbracht aber alles ohne Erfolg.
Hat hier noch jemand einen Tipp wie ich das mit Blocky/ECMA Script umsetzen kann?

Gruß Lenschi

Re: Stoppuhr

Verfasst: 1. Nov 2022 13:53
von udo1toni
AH, ja, das ist tatsächlich etwas anderes. Die einfachste Variante, mit einem String Item (im Beispiel myCounterItem):

Code: Alles auswählen

// globale Variablen werden zu Beginn der *.rules Datei definiert, vor der ersten Rule
var Timer tWasch = null                                         // Timer Variable für Counter
var Integer iWasch = 0                                          // Minutenzähler für Waschmaschine

rule "Betriebsdauer messen"
when
    Item Waschmaschine changed                                  // wechselt auf ON oder OFF
then
    tWasch?.cancel                                              // Timer löschen, falls vorhanden
    if(newState == OFF) {                                       // falls neuer Zustand OFF
        myCounterItem.postUpdate("00:00:00")                    // setze Anzeige auf 0
        return;                                                 // und beende die Rule
    } else {                                                    // falls neuer Zustand nicht OFF (also ON)
        iWasch = 0                                              // setze Zähler auf 0
        tWasch = createTimer(now.plusMinutes(1),[|              // Lege Timer an, der in einer Minute auslöst
            iWasch += 1                                         // erhöhe den Zähler um eins
            val iHour = (iWasch/60).intValue                    // Stundenanteil bestimmen
            val iMinute = iWasch - iHour * 60                   // Minutenanteil bestimmen
            var strState = if(iHour<10)"0" else ""              // falls weniger als 10 Stunden führende 0
            strState = strState + iHour.toString                // Anzahl Stunden
            strState = strState + if(iMinute<10) ":0" else ":"  // Falls weniger als 10 Minuten führende 0
            strState = strState + iMinute.toString+":00"        // Anzahl Minuten
            myCounterItem.postUpdate(strState)                  // Item updaten
            tWasch.reschedule(now.plusMinutes(1))               // Timner erneut planen
        ])
    }
end
Allgemein kann man das auch mit einem DateTime Item machen (und sich dann das Jonglieren mit führenden Nullen schenken). Allerdings ist das Hantieren mit DateTime deutlich komplexer als die gezeigte Variante. Der neue Status des Anzeigeitems kann auch in einer Zeile angegeben werden, hier nur der Übersichtlichkeit halber als mehrere getrennte Operationen...

Re: Stoppuhr

Verfasst: 1. Nov 2022 21:10
von lenschith
Hallo Udo,
ich wollte das jetzt implementieren aber irgendwie stehe ich voll auf der Leitung und bekomme das nicht gebacken über die UI in OH3?
ich habe eine Rule über die UI angelegt und bekommen diese Fehlermeldung im Log:

Code: Alles auswählen

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Timer_Geschirrspueler' failed: var Timer tWasch = null

Code: Alles auswählen

   1. Cannot refer to the non-final variable iWasch inside a lambda expression; line 11, column 872, length 6

   2. Type mismatch: cannot convert from int to Integer; line 11, column 879, length 2

   3. Cannot refer to the non-final variable iWasch inside a lambda expression; line 12, column 978, length 6

   4. Cannot refer to the non-final variable iWasch inside a lambda expression; line 13, column 1070, length 6

   5. Cannot refer to the non-final variable tWasch inside a lambda expression; line 19, column 1605, length 6
Was mache ich falsch bzw. wo liegt denn da bei mir der Fehler. Ich habe schon länger nichts mehr mit den DSL Rules gemacht und mach seit dem Umstieg auf OH3 alles über die UI.

CODE:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: TestSwitch
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >
        var Timer tWasch = null                                         // Timer
        Variable für Counter

        var Integer iWasch = 0                                          // Minutenzähler für Waschmaschine

            tWasch?.cancel                                              // Timer löschen, falls vorhanden
            if(newState == OFF) {                                       // falls neuer Zustand OFF
                GeschirrspuelerTimer.postUpdate("00:00:00")                    // setze Anzeige auf 0
                return;                                                 // und beende die Rule
            } else {                                                    // falls neuer Zustand nicht OFF (also ON)
                iWasch = 0                                              // setze Zähler auf 0
                tWasch = createTimer(now.plusMinutes(1),[|              // Lege Timer an, der in einer Minute auslöst
                    iWasch += 1                                         // erhöhe den Zähler um eins
                    val iHour = (iWasch/60).intValue                    // Stundenanteil bestimmen
                    val iMinute = iWasch - iHour * 60                   // Minutenanteil bestimmen
                    var strState = if(iHour<10)"0" else ""              // falls weniger als 10 Stunden führende 0
                    strState = strState + iHour.toString                // Anzahl Stunden
                    strState = strState + if(iMinute<10) ":0" else ":"  // Falls weniger als 10 Minuten führende 0
                    strState = strState + iMinute.toString+":00"        // Anzahl Minuten
                    GeschirrspuelerTimer.postUpdate(strState)                  // Item updaten
                    tWasch.reschedule(now.plusMinutes(1))               // Timner erneut planen
                ])
            }
    type: script.ScriptAction
Das Item GeschirrspuelerTimer ist als STRING deklariert.

Oder muss ich hier wieder über Rule Files arbeiten und nicht über die UI?

Re: Stoppuhr

Verfasst: 2. Nov 2022 02:01
von udo1toni
Nein, die Rule kann nicht über die UI angelegt werden, das geht ausschließlich über die Rules Textdateien, das liegt daran, dass die verwendeten Variablen global sein müssen.
Grundsätzlich, wenn man Timer in der vorgeführten Version nutzen möchte (und das ist die einfachste Art, diese Aufgabe zu erledigen) wird das meistens nur über die ursprüngliche Form der DSL Rules gehen.

Re: Stoppuhr

Verfasst: 2. Nov 2022 14:55
von lenschith
Danke Udo, klapp wie gewollt.
Gruß Lenschi

Re: [GELÖST] Stoppuhr

Verfasst: 2. Nov 2022 17:44
von Harka
schön das es klappt.
Falls es doch mal jemand Udos Lösung, so wie ich gestern Abend (aus reiner Neugier und in abgewandelter Form) getan habe, mit Blockly nachbauen möchte -> geht.
Für die globale Variable einfach stored_value nutzen (wie? ist in der Hilfe beschrieben) und die Timer Funktionen inklusive reschedule sind auch von Haus aus enthalten. Damit kann die Lösung als Blockly/ECMA auch über die UI verwaltet werden.

Re: [GELÖST] Stoppuhr

Verfasst: 2. Nov 2022 18:01
von lenschith
Kannst du mal das blockly Script posten. Ich hab soviel getestet und gelesen aber habs nicht geschafft. Würde es interessieren damit ich fürs nächste mal ne weitere Option habe.

Re: [GELÖST] Stoppuhr

Verfasst: 2. Nov 2022 18:33
von Harka
Timer.jpg
musst halt innerhalb des Timers noch die Ausgabe entsprechend einfügen (was aber kein Problem sein sollte). Wie gesagt, habe die Regel etwas anders verwendet (aus reiner Neugier - ohne höheren Sinn) .