Seite 2 von 3

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 3. Dez 2022 20:13
von udo1toni
Absinthe hat geschrieben: 3. Dez 2022 17:14 Ich hab dieses auf:

Code: Alles auswählen

        message.append(new DateTimeType().format("%1$td.%1$tm.%1$ty %1$tH:%1$tM"))
abgeändert damit es funktioniert.
Na sowas, hab ich glatt das Leerzeichen verschluckt... guter Catch. :)

Es gibt Bücher und Webseiten zum Thema Programmieren. Soll es mit der openHAB DSL sein, wird es schon schwieriger mit Literatur. Was ich anwende, ist learning by doing. Mit der Zeit begegnen einem hier und vor allem im englischen Forum aber jede Menge coole Ansätze, die man dann und wann aus der Kiste zaubern kann :)

Ganz grundsätzlich setzt die DSL auf XTend auf. XTend ist ein Framework um DSL (Domain Specific Languages) zu gestalten. XTend ist in Java geschrieben, weshalb man viele Dinge ganz ähnlich lösen kann wie in Java. Allerdings gibt es auch diverse Unterschiede, so dass es nicht reicht, sich das nächste "Lerne Java" Buch zu schnappen. Die DSL ist vor allem darauf ausgelegt, sich möglichst wenig mit dem Drumherum beschäftigen zu müssen. Es gibt Items, die als Objekte direkt zur Verfügung stehen. Da die DSL objektorientiert arbeitet, gibt es die passenden Methoden obendrauf, also .postUpdate() um den Status eines Items zu setzen und .sendCommand() um einen Befehl an das Item zu senden, welches diesen Befehl dann an Rules und/oder verlinkte Channel weiterleitet. Darüber hinaus gibt es noch eine Handvoll weitere Funktionen, if(), switch(), createTimer(), um die (für mich) wichtigsten zu nennen. Und natürlich die log-Befehle logDebug(), logInfo(), logWarn() und logError(), welche auch sehr nützlich sind, gerade wenn man eine Rule neu entwickelt. Weil Items unterschiedliche Datentypen enthalten können, braucht es noch ein paar Werkzeuge, um diese in dne Griff zu bekommen, entweder per Methode (.toString() wäre so etwas) oder auch per Type Casting (.state as Number wäre da ein bekanntes Beispiel).
Und wenn das nicht reicht, importiert man halt die notwendigen Dinge (die wichtigsten sind bereits importiert und können einfach genutzt werden, wie now() mit all dem, was dazu gehört oder auch diverse mathematische Funktionen per Math. oder auch das parsen von Zeichenketten zu Zahlen (Integer.parseInt("1234567") "1234567" ist in diesem Fall keine Zahl, sondern eine Zeichenkette, die eine Zahl enthält. Um diese als Zahl verwenden zu können, muss sie erst gewandelt werden.)

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 5. Feb 2023 14:40
von Absinthe
Hallo zusammen,
hallo udo1toni,

die Rule funktioniert bis auf eine kleine Ausnahme einwandfrei :) Ich habe für die Rule einen Crown mit 6 Stunden eingerichtet- .
udo1toni hat geschrieben: 28. Nov 2022 17:35

Code: Alles auswählen

val StringBuilder message = new StringBuilder()
val myList = Group_Licht.members.filter[light|light.state==ON && !light.changedSince(now.minusSeconds(1))]
[...]

Aus (now.minusSeconds(1)) wurde (now.minusHours(12)). Dies hat einen kleinen aber unschönen Nebeneffekt. Wenn z.B. das Licht in der Küche Vormittags angeschaltet war und dann aus und dann wieder angeschaltet wird, erkennt die Rule nicht, dass das Licht aus war und meldet das Licht als länger als 12 Stunden eingeschaltet. Eigentlich sollte keine Meldung erfolgen, da das Licht zwischenzeitlich ausgeschaltet wurde.

Jemand eine gute und schlanke Idee das zu lösen?

Grüße

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 5. Feb 2023 17:15
von udo1toni
das kann eigentlich nicht sein. changedSince meldet true, wenn der Status mindestens einmal innerhalb des Zeitraums x bis jetzt geändert wurde. Es meldet nur dann false, wenn sich der Zustand innerhalb des Zeitraums nie geändert hat.
Oder zumindest sollte es so sein :)

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 7. Feb 2023 19:53
von Absinthe
Hallo udo1toni,

kann ich so leider nicht bestätigen oder - was vermutlich wahrscheinlicher ist - ist in meiner Rule ein Fehler drin...

Was passiert:

Ich habe einen Crown eingerichtet, der alle 6 Stunden die Rule ausführt. Wenn das Licht länger als 12 Stunden brennt, meldet die Rule dies brav. Allerdings meldet die Rule auch alle Lichter, die innerhalb der 12 Stunden an- und ausgeschaltet waren und wieder angeschaltet sind UND zum Zeitpunkt der Ruleprüfung angeschaltet sind. Es sollten aber nur Lichter gemeldet werden, die länger als 12 Stunden angeschaltet sind. Wenn diese ausgeschaltet werden, sollte der Zeitraum von vorne beginnen. Ich hoffe, dass war so verständlich ;)

Oder habe ich hier einen grundsätzlichen Denkfehler?!

Grüße

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 7. Feb 2023 20:23
von udo1toni
Wie ist denn die exakte Zeile in Deiner Rule? Du hast ja nur meine Zeile hier gepostet...

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 7. Feb 2023 21:48
von Absinthe
Sorry @udi1toni. Hätte ich direkt mit posten können.

Hier die ganze Rule:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      cronExpression: 0 0 10,14,18,22 * * ? *
    type: timer.GenericCronTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        val StringBuilder message = new StringBuilder()


        val myList = Group_Licht.members.filter[light|light.state==ON && !light.changedSince(now.minusHours(12))]


        if(myList.size == 0)
            return;

        if(myList.size == 1)
            message.append("Das Licht ")
        else
            message.append("Die Lichter ")

        myList.forEach[light, element |
            if(element > 0) {
                if(element < myList.size - 1)
                    message.append(", ")
                else 
                    message.append(" und ")
            }
            message.append(light.label)
        ]


        if(myList.size == 1)
            message.append(" ist ")
        else
            message.append(" sind ")

        message.append("seit mehr als 12 Stunden eingeschaltet. Nachricht von ")

        message.append(new DateTimeType().format("%1$td.%1$tm.%1$ty %1$tH:%1$tM"))

        message.append(" Uhr.")


        val Nachricht = message.toString
          
        val mailActions = getActions("mail","mail:smtp:Mail_SMTP")

        val pushoverActions = getActions("pushover", "pushover:pushover-account:XXX")

        val success = mailActions.sendMail("E-Mail", "openHab - Hinweis", Nachricht)

        pushoverActions.sendPriorityMessage(Nachricht,"openHab - Hinweis",0)
    type: script.ScriptAction
Viel anders, als die Zeit von Sekunden zu Stunden ist deine Lösung nicht abgeändert... mich verwundert nur das Verhalten, dass je definitiv ein "Schaltvorgang" stattfindet - an und aus - aber dennoch diese als "AN" zu dem Zeitpunkt gesehen wird... Also ob das && eher als ODER gesehen wird...

Jemand eine Idee?

Auf der Suche nach eine Lösung habe ich mal ChatGBT befragt... erstaunlich was das Teil alles kann - auch im Bereich Rules für OH3...

Die AI schlägt als Lösung lastUpdate vor...

Code: Alles auswählen

val myList = Group_Licht.members.filter[light|light.state==ON && light.lastUpdate.plusHours(12).isBeforeNow]

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 11. Feb 2023 11:21
von Absinthe
Absinthe hat geschrieben: 7. Feb 2023 21:48 Auf der Suche nach eine Lösung habe ich mal ChatGBT befragt... erstaunlich was das Teil alles kann - auch im Bereich Rules für OH3...

Die AI schlägt als Lösung lastUpdate vor...

Code: Alles auswählen

val myList = Group_Licht.members.filter[light|light.state==ON && light.lastUpdate.plusHours(12).isBeforeNow]
So klug war leider die Lösung nicht... hatte direkt übersehen, dass ZonedDateTime formatiert werden müsste...

Jemand eine Idee, warum die geniale Lösung von @udo1toni sich so seltsam verhält?

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 11. Feb 2023 15:01
von udo1toni
Also, ChatGPT mag als Spielerei ganz nett sein, letztlich ist es nur eine große Datenbank mit jeder Menge Müll.
Und auch hier ist das Ergebnis mindestens fragwürdig, denn selbst wenn man den Typfehler mal außen vor lässt, kann ein Item sekündlich mit immer dem selben Wert aktualisiert werden, das ändert aber nichts an seinem Zustand.
Wir brauchen wenn, dann den Zeitpunkt der letzten Änderung.
Den bekommt man auch, und zwar mit .previousState(true).getTimestamp. Dabei erzwingt das true den letzten Wert, der vom aktuellen Wert abweicht.

Übrigens ist der Code nicht auf meinem Mist gewachsen :) steht alles in der Doku drin. Und das muss auch so funktionieren. Für mich einzig mögliche Erklärung: die verwendete Datenbank macht da Mist.

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 12. Feb 2023 12:12
von Absinthe
udo1toni hat geschrieben: 11. Feb 2023 15:01 Übrigens ist der Code nicht auf meinem Mist gewachsen steht alles in der Doku drin. Und das muss auch so funktionieren. Für mich einzig mögliche Erklärung: die verwendete Datenbank macht da Mist.
Aber die Idee, dies so einzusetzen ;)

Ich setzte für die persistence rrdj4 ein.

Code: Alles auswählen

Strategies {
        everyHour : "0 0 * * * ?"
        everyDay  : "0 0 0 * * ?"
       default = everyChange
}
Items {
        *: strategy = everyChange, everyHour, restoreOnStartup
        Temperature*, Weather* : strategy = everyHour
}
Ich kann im OH3 auch, wenn ich im meldeten ITEM, auf "Analysieren" klicke, sehen, wann dieses in den letzten 7 Tagen an bzw. aus war...

Da die rrdj4 eigentlich nicht zum auslesen einzelner Werte gedacht ist - eine Idee, wie ich schimmlige Daten finden könnte?

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Verfasst: 12. Feb 2023 14:41
von udo1toni
Ah, das erklärt es. rrd4j erfordert zwingend(!) everyMinute als Strategy, ohne Wenn und Aber. Es spielt für die Größe der Datenbank dabei keine Rolle, da rrd4j statisch arbeitet (die Größe der Dateien ändert sich nicht, egal wie oft die Daten geschrieben werden).