Seite 1 von 1

Funktionsbaustein analog steuerungstechnik

Verfasst: 3. Jan 2023 21:57
von AndyRPi
Ich frage mich wie ein Funktionsbaustein realisiert werden kann.
Ich habe folgendes mir überlegt:
Sowie das Fenster in einem Raum geöffnet wird soll die aktuelle Temperatur gespeichert werden. Sowie die Temperatur dann um zwei grad steigt oder fällt will ich eine Benachrichtigung.
Nun kann ich das für jeden Raum einzeln programmieren.
Gibt es eine Möglichkeit einen parametrierbaren Baustein zu machen das das erledigt und einfach für die Verwendung parametriert wird. Ich kenn das von der sps so.

Re: Funktionsbaustein analog steuerungstechnik

Verfasst: 3. Jan 2023 23:07
von udo1toni
Es gibt verschiedene Möglichkeiten, dieses Problem anzugehen.
Was Du möchtest, ist letztlich ein Makro, welches parametriert werden kann. Das ist in openHAB eher umständlich zu realisieren. Du könntest aber natürlich eine (externe) Funktion dafür schreiben, die Du dann aus diversen Rules aufrufst.

Die bessere Alternative wird sein, das über Gruppen zu realisieren. Mittels Gruppen kann man gleichartige Items zusammenfassen und dann eine Rule für alle Items verwenden. Leider ist das nicht trivial, aber so als Idee:

Code: Alles auswählen

rule "fenster auf oder zu"
when
    Item Fenster changed
then
    if(fenster1.state == OPEN)
        tempStore1.postUpdate(tempIst1.state)
    else
        tempStore1.postUpdate(-999)
end

rule "temperatur update"
when
    Item tempIst1 changed
then
    if(tempStore1.state == -999)
        return;

    if(Math.abs(tempIst1.state - tempStore1.state) > 2) {
        fensterAlarm1.postUpdate(ON)
        // Meldung für Fenster 1 ausgeben
        logInfo("tempAlarm","Fenster 1 ist geöffnet, Temperaturdifferenz seit Öffnen auf über 2 °C gestiegen!")
    }
end
So sähe der Code mehr oder weniger aus, um ein Fenster abzudecken. Die eine Rule kümmert sich um den Fensterkontakt und schreibt die aktuelle Temperatur des Raums in den zugehörigen Speicher. Ist das Fenster geschlossen, wird stattdessen ein unsinniger Wert gespeichert (-999).

Die zweite Rule wird ausgelöst, wenn sich die aktuelle Temperatur ändert. Befindet sich die unsinnige Temperatur im Store, so bricht die Rule ab. (alternativ könnte man auch prüfen, ob das Fenster geschlossen ist...) Ansonsten wird der Absolutwert nach Subtraktion der beiden Temperaturen ermittelt. Ist dieser über 2, so weicht die aktuelle Temperatur um mehr zwei Grad ab und es erfolgt eine Alarmierung, in welcher Form auch immer.

Möchte man das Ganze nun generalisieren, so müssen die Items in Gruppen gepackt werden, mit verschiedenen Optionen. Einfach: alle Fensterkontakte in eine Gruppe, alle Temperaturen in eine zweite Gruppe, alle Stors für die Temperaturen in eine dritte Gruppe, alle Alarmspeicher (falls gewünscht) in eine vierte Gruppe. Nennen wir die Gruppen gFenster, gTempIs, gTempStore und gTempAlarm.
Wichtig ist, dass alle Items Namen tragen, die zueinander passen, also z.B.
Fenster_Wohnzimmer Temperatur_Wohnzimmer TempStore_Wohnzimmer, Alarm_Wohnzimmer

Nun können wir die Rules generalisieren:

Code: Alles auswählen

rule "Fenster auf oder zu"
when
    Member of gFenster changed
then
    val strRoom = triggeringItem.name.split("_").get(1) // Name des Raums
    val tempIs    = gTempIs.members.filter[i|   i.name.endsWith(strRoom)].head
    val tempStore = gTempStore.members.filter[i|i.name.endsWith(strRoom)].head
    if(newState == OPEN)
        tempStore.postUpdate(tempIs.state)
    else
        tempStore.postUpdate(-999)
end

rule "Temperatur update"
when
    Member of gTempIs changed
then
    val strRoom = triggeringItem.name.split("_").get(1) // Name des Raums
    val tempStore = gTempStore.members.filter[i|i.name.endsWith(strRoom)].head
    val tempalarm = gTempalarm.members.filter[i|i.name.endsWith(strRoom)].head

    if(tempStore.state == -999)
        return;

    if(Math.abs(newState - tempStore.state) > 2) {
        tempAlarm.postUpdate(ON)
        // Meldung mit Bezug auf strRoom ausgeben
        logInfo("tempAlarm","Fenster im {} ist geöffnet, Temperaturdifferenz seit Öffnen auf über 2 °C gestiegen!",strRoom)
    }
end
Zu Beginn der Rules wird also ermittelt, welche Items zu dem Item gehören, welches die Rule ausgelöst hat- anschließend werden diese Items verwendet. Im Grunde ist das also recht einfach. Wichtig ist nur, dass die Namen der Räume alle eindeutig sind. Gibt es z.B. zwei Wohnzimmer, so muss eine weitere Unterscheidung in den Namen aufgenommen werden, z.B. OGWohnzimmer und EGWohnzimmer. Da der Teil hinter dem Unterstrich komplett als Raumname verwendet wird, darf auch kein Name Teil eines anderen Namens sein, OGWohnzimmer und Wohnzimmer ginge also nicht.

Dafür reichen tatsächlich diese beiden Rules, um beliebig viele Räume mit der Funktion auszustatten.

Re: Funktionsbaustein analog steuerungstechnik

Verfasst: 4. Jan 2023 10:57
von AndyRPi
Vielen Dank für den Input.
Ich nutze bisher blockly. Sind deine rules DSL Rules?
Ich mach alles über die UI.

Ich setz mich nun dran und probiere das aus.
udo1toni hat geschrieben: 3. Jan 2023 23:07 Es gibt verschiedene Möglichkeiten, dieses Problem anzugehen.
Was Du möchtest, ist letztlich ein Makro, welches parametriert werden kann. Das ist in openHAB eher umständlich zu realisieren. Du könntest aber natürlich eine (externe) Funktion dafür schreiben, die Du dann aus diversen Rules aufrufst.

Die bessere Alternative wird sein, das über Gruppen zu realisieren. Mittels Gruppen kann man gleichartige Items zusammenfassen und dann eine Rule für alle Items verwenden. Leider ist das nicht trivial, aber so als Idee:

Code: Alles auswählen

rule "fenster auf oder zu"
when
    Item Fenster changed
then
    if(fenster1.state == OPEN)
        tempStore1.postUpdate(tempIst1.state)
    else
        tempStore1.postUpdate(-999)
end

rule "temperatur update"
when
    Item tempIst1 changed
then
    if(tempStore1.state == -999)
        return;

    if(Math.abs(tempIst1.state - tempStore1.state) > 2) {
        fensterAlarm1.postUpdate(ON)
        // Meldung für Fenster 1 ausgeben
        logInfo("tempAlarm","Fenster 1 ist geöffnet, Temperaturdifferenz seit Öffnen auf über 2 °C gestiegen!")
    }
end
So sähe der Code mehr oder weniger aus, um ein Fenster abzudecken. Die eine Rule kümmert sich um den Fensterkontakt und schreibt die aktuelle Temperatur des Raums in den zugehörigen Speicher. Ist das Fenster geschlossen, wird stattdessen ein unsinniger Wert gespeichert (-999).

Die zweite Rule wird ausgelöst, wenn sich die aktuelle Temperatur ändert. Befindet sich die unsinnige Temperatur im Store, so bricht die Rule ab. (alternativ könnte man auch prüfen, ob das Fenster geschlossen ist...) Ansonsten wird der Absolutwert nach Subtraktion der beiden Temperaturen ermittelt. Ist dieser über 2, so weicht die aktuelle Temperatur um mehr zwei Grad ab und es erfolgt eine Alarmierung, in welcher Form auch immer.

Möchte man das Ganze nun generalisieren, so müssen die Items in Gruppen gepackt werden, mit verschiedenen Optionen. Einfach: alle Fensterkontakte in eine Gruppe, alle Temperaturen in eine zweite Gruppe, alle Stors für die Temperaturen in eine dritte Gruppe, alle Alarmspeicher (falls gewünscht) in eine vierte Gruppe. Nennen wir die Gruppen gFenster, gTempIs, gTempStore und gTempAlarm.
Wichtig ist, dass alle Items Namen tragen, die zueinander passen, also z.B.
Fenster_Wohnzimmer Temperatur_Wohnzimmer TempStore_Wohnzimmer, Alarm_Wohnzimmer

Nun können wir die Rules generalisieren:

Code: Alles auswählen

rule "Fenster auf oder zu"
when
    Member of gFenster changed
then
    val strRoom = triggeringItem.name.split("_").get(1) // Name des Raums
    val tempIs    = gTempIs.members.filter[i|   i.name.endsWith(strRoom)].head
    val tempStore = gTempStore.members.filter[i|i.name.endsWith(strRoom)].head
    if(newState == OPEN)
        tempStore.postUpdate(tempIs.state)
    else
        tempStore.postUpdate(-999)
end

rule "Temperatur update"
when
    Member of gTempIs changed
then
    val strRoom = triggeringItem.name.split("_").get(1) // Name des Raums
    val tempStore = gTempStore.members.filter[i|i.name.endsWith(strRoom)].head
    val tempalarm = gTempalarm.members.filter[i|i.name.endsWith(strRoom)].head

    if(tempStore.state == -999)
        return;

    if(Math.abs(newState - tempStore.state) > 2) {
        tempAlarm.postUpdate(ON)
        // Meldung mit Bezug auf strRoom ausgeben
        logInfo("tempAlarm","Fenster im {} ist geöffnet, Temperaturdifferenz seit Öffnen auf über 2 °C gestiegen!",strRoom)
    }
end
Zu Beginn der Rules wird also ermittelt, welche Items zu dem Item gehören, welches die Rule ausgelöst hat- anschließend werden diese Items verwendet. Im Grunde ist das also recht einfach. Wichtig ist nur, dass die Namen der Räume alle eindeutig sind. Gibt es z.B. zwei Wohnzimmer, so muss eine weitere Unterscheidung in den Namen aufgenommen werden, z.B. OGWohnzimmer und EGWohnzimmer. Da der Teil hinter dem Unterstrich komplett als Raumname verwendet wird, darf auch kein Name Teil eines anderen Namens sein, OGWohnzimmer und Wohnzimmer ginge also nicht.

Dafür reichen tatsächlich diese beiden Rules, um beliebig viele Räume mit der Funktion auszustatten.

Re: Funktionsbaustein analog steuerungstechnik

Verfasst: 4. Jan 2023 14:08
von AndyRPi
Ich mir das nochmals durchdacht. Ich glaube mit Gruppen ist das nicht perfekt. Die Gruppe Fenster ändert ja ihren Status nur einmal, wenn in der Zeit weitere Fenster geöffnet werden wird nicht neu geschaut.

Re: Funktionsbaustein analog steuerungstechnik

Verfasst: 4. Jan 2023 16:02
von udo1toni
Die Gruppe hat überhaupt keinen Zustand.
Die Gruppe wird lediglich dazu verwendet, Items gemeinsam nach bestimmten Regeln gleich zu behandeln.
Wenn Du genau liest, sieht Du, dass an jeder Stelle von einem Member der Gruppe die Rede ist, niemals von der Gruppe selbst.
Trigger: Member of ... changed -> Ein Item, welches in der Gruppe ist, hat den Status geändert.
groupitem.members.filter[...].head -> nimm das erste Item (.head), welches zur Gruppe groupitem gehört (.members), für dass die im filter gesetzten Bedingungen zutreffen.

Du kannst diese Rules auch über Blockly bauen, allerdings ist es mit deutliche mehr Aufwand verbunden.
Blockly ist eine tolle Möglichkeit, in openHAB Regeln zu definieren, genauso wie Rules ganz ohne Codeblock eine tolle Sache sind.
Für das vorliegende Problem ist das alles aber nur bedingt brauchbar. Man nimmt keinen Hammer, um eine Schraube in die Wand zu treiben, ebenso nutzt man keinen Schraubendreher, um einen Nagel in die Wand zu drehen. Oder anders ausgedrückt: Nutze von den zur Verfügung stehenden Werkzeugen die, welche sinnvoll sind, nicht die, welche Du schon kennst.

Und bitte kein Tofu.

Re: Funktionsbaustein analog steuerungstechnik

Verfasst: 4. Jan 2023 16:17
von Harka
jetzt war Udo schneller aber ich stell mal dennoch das Blockly-Beispiel rein welches ich hier gerade erstellt habe.
Bei gFenster wird hier wird ermittelt welches Fenster sich geändert hat und welchen Status dieses nun hat.
Unten ist noch eine weitere Möglichkeit aufgeführt den Fenster die Thermometer zuzuweisen. Dann musst Du ev. nur die restlichen Variablen selbst basteln.
ForumGruppeFenster.jpg

Re: Funktionsbaustein analog steuerungstechnik

Verfasst: 6. Jan 2023 14:26
von AndyRPi
Harka hat geschrieben: 4. Jan 2023 16:17 jetzt war Udo schneller aber ich stell mal dennoch das Blockly-Beispiel rein welches ich hier gerade erstellt habe.
Bei gFenster wird hier wird ermittelt welches Fenster sich geändert hat und welchen Status dieses nun hat.
Unten ist noch eine weitere Möglichkeit aufgeführt den Fenster die Thermometer zuzuweisen. Dann musst Du ev. nur die restlichen Variablen selbst basteln. ForumGruppeFenster.jpg
Ich habe heute endlich mal Zeit zum probieren gehabt. Der obere Teil hat funktioniert in meinem Testaufbau.
Leider wirft mir der untere Teil einen Fehler aus.
Kann mir dabei jemand helfen. Hab ich da was Falsch verstanden?
log.JPG
regel.JPG

Re: Funktionsbaustein analog steuerungstechnik

Verfasst: 6. Jan 2023 14:45
von Harka
Hi,
an Stelle von "Links" u.s.w. muss dort der ID-Name des verknüpften Items rein. Ersetze den String "Links" mal durch get_name_of_item und klick das richtige Item an. Später solltest du aber ruhig wieder auf String (mit dem nun angezeigtem Namen) zurück gehen weil dies vom Rechenaufwand her effizienter ist.

Anmerkung - diesen Teil brauchst Du nur wenn sich vom Namen des Fensters sich nicht automatisch der Name des Temperatursensors ableiten lässt (und umgekehrt). Andernfalls dürften die List-Befehle eine bessere Wahl sein.

Re: Funktionsbaustein analog steuerungstechnik

Verfasst: 7. Jan 2023 07:51
von Harka
Moin,
weil mich das Ganze gereizt hat habe ich mal versucht einen kompletten Lösungsansatz zu basteln. Die Regel hätte 2 Trigger mit den Gruppen Fenster und Temperatur der betreffenden Räume. Annahme ist hier das die Zimmer jeweils ein Temperatursensor mit der ID Temp_Zimmer haben. Gespeichert wird die Temperatur beim Öffnen in einer globalen Variable pro Zimmer. Achtung - ich konnte es nur ansatzweise Testen.
ZimmerTemp.jpg