Umgang mit Rules

Moderatoren: seppy, udo1toni

Mops
Beiträge: 17
Registriert: 7. Aug 2020 11:52

Umgang mit Rules

Beitrag von Mops »

Hallo zusammen,

ich habe eine ganz Grundsätzliche Frage zu Rules.
Ich habe ein bestehendes KNX-System, welches über OpenHAB über die BasicUI gesteuert werden kann.

Nun möchte ich gerne einen MDT Glastaster mit einbinden. Dieser ist schon vorhanden. Er ist über ETS mit den Schaltaktoren verknüpft worden und kann diese auch steuern.
Jetzt möchte ich das gerne in OpenHAB so programmieren, dass das Signal vom Taster eingelesen wird und somit ein Kanal des Aktors geschaltet wird.

Ist es möglich den Tasten des Glastasters anderen Kanälen des Schaltaktors zuzuweisen? Bsp. Die Taste A schatet nicht mehr Lampe 1, sondern Lampe 2.
Ich hatte da an Switch-case gedacht, mit auswahl über Variablen.

Probiert habe ich das ganze schon einmal mit weniger Erfolg:

knx.things:

Code: Alles auswählen

Thing device GT_1_1_1 "MDT 1.1.1"[
]{
Type switch-control : Glastaster_A "Glastaster Taste A" [ga="1.001:1/1/1+<1/1/11"]
}
knx.items:

Code: Alles auswählen

Switch Glastaster_A "Glastaster Taste A" 
{ channel="knx:device:bridge:SA_1_1_1:Glastaster_A"}
knx.rules:

Code: Alles auswählen

rule "Flur Lampen AN"
when 
  Item Glastaster_A received command ON
then 
  Flur.sendCommand(ON)
end
(Die Gruppenadresse 1/1/1 ist mittels ETS mit der Taste A des Glastasters verbunden, sowie mit der Wohnzimmer Lampe. Die Taste soll jetzt aber über die Rule die Lampe im Flur schalten, welche über eine andere Gruppenadresse verfügt)

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Umgang mit Rules

Beitrag von udo1toni »

Nein, das geht so nicht.

Du musst Dir klar machen, dass Du schon auf knx-Ebene eine Verknüpfung zwischen Aktor und Taster hast. openHAB kann daran nichts ändern.

In openHAB steuerst Du immer Aktoren. Auch in knx werden immer Aktoren gesteuert. Wenn mehrere Taster den gleichen Aktor steuern sollen, so wird in allen Tastern die gleiche GA eingetragen, die im Aktor als Steuer-GA eingetragen ist.
Soll der Aktor zusätzlich über Szenen gesteuert werden (mit im Aktor integrierter Szenensteuerung) so muss zwingend auch noch die Rückmelde-GA als 2. GA in den Tastern eingetragen werden, damit die Taster Kenntnis über den aktuelle Schaltzustand haben, da knx kein Toggle-Kommando kennt. Jeder Taster, der toggelt, merkt sich also die aktuelle Schaltstellung.
Das gleiche gilt, wenn man eine Zentralfunktion nutzt (die Zentral-GA wird dazu als 2. GA mit dem Aktor Steuer-KO verbunden).

Wenn Du mit dem Glastaster fallweise unterschiedliche Leuchten steuern möchtest, so muss der Taster eine eigene GA bekommen, die nicht mit einem Aktor verknüpft ist. Stattdessen wird die GA in openHAB als switch-command Channel angelegt. Nun empfängt openHAB Commands über diese GA und Du kannst eine Rule programmieren, welche dann die gewünschten Aktionen ausführt (z.B. Am Ostersonntag statt dem Deckenlicht den Osterhasen einschalten, oder nach 18 Uhr eine andere Leuchte schalten als tagsüber, oder, oder, oder...


Gesendet von iPad mit Tapatalk
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Mops
Beiträge: 17
Registriert: 7. Aug 2020 11:52

Re: Umgang mit Rules

Beitrag von Mops »

Hallo udo1toni,

vielen Dank für den Tipp. Funktioniert bestens. Sogar mit Switch case, abhängig von einer Variable.

Weißt du, wie ich in der Basic UI oder besser noch im Habpanel eine Art Auswahl implementieren kann, über die diese und weitere Swtich Case Variablen ausgewählt werden können? Über ein Dropdown Menü oder ähnliches.

Also z.B.:
Menüpunkt: Taster A -> Auswahl -> 1-7 -> Auswahl 2 wird getroffen -> Entsprechende Switch Case Variable wird auf 2 gesetzt.

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Umgang mit Rules

Beitrag von udo1toni »

Ja sicher, das ist leicht. Am einfachsten verwendest Du ein Number Item

Code: Alles auswählen

Number selectButton_A "Taster A Auswahl"
in der Sitemap:

Code: Alles auswählen

Selection item=selectButton_A mappings=[1="Auswahl 1",2="Auswahl 2",3="Auswahl 3",4="Auswahl 4",5="Auswahl 5",6="Auswahl 6",7="Auswahl 7"]
Selbstverständlich sind hier beliebige Texte für die Menüpunkte möglich.
Leider wird nun die getroffene Auswahl in der Sitemap nicht angezeigt. Das kann man aber mit einem Mapping beheben:

Andere Itemdefinition:

Code: Alles auswählen

Number selectButton_A "Taster A Auswahl [MAP(taster_a.map):%s]"
und die Datei taster_a.map:

Code: Alles auswählen

1=Auswahl 1
2=Auswahl 2
3=Auswahl 3
4=Auswahl 4
5=Auswahl 5
6=Auswahl 6
7=Auswahl 7
-=-
NULL=-
Nachteil des Ganzen: Du musst die Label der Auswahl an zwei Stellen pflegen.

Nun kannst Du die Rule einfach so gestalten:

Code: Alles auswählen

rule "Taster A"
when
    Item Taster_A received command
then
    var Integer iSelect = 0
    if(selectButton_A.state instanceof Number)
        iSelect = (selectButton_A.state as Number).intValue
    switch(iSelect) {
        case 1: {
            Auswahl_1.sendCommand(receivedCommand)
        }
        case 2: {
            Auswahl_2.sendCommand(receivedCommand)
        }
        case 3: {
            Auswahl_3.sendCommand(receivedCommand)
        }
        case 4: {
            Auswahl_4.sendCommand(receivedCommand)
        }
        case 5: {
            Auswahl_5.sendCommand(receivedCommand)
        }
        case 6: {
            Auswahl_6.sendCommand(receivedCommand)
        }
        case 7: {
            Auswahl_7.sendCommand(receivedCommand)
        }
        default: {
            logWarn("tasterA","Ungültige Auswahl: {}",selectButton_A.state)
        }
    }
end
Die Alternative wäre, direkt ein String Item zu verwenden, dafür musst Du dann im case den korrekten String verwenden.
Das Konstrukt mit der Variablen iSelect erlaubt, bei nicht gesetztem Wert eine Default Auswahl zu treffen (also statt var Integer iSelect = 0 z.B. var Integer iSelect = 4)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

thomas_w

Re: Umgang mit Rules

Beitrag von thomas_w »

udo1toni hat geschrieben: 19. Aug 2020 14:20 :

Code: Alles auswählen

rule "Taster A"
when
    Item Taster_A received command
then
    var Integer iSelect = 0
    if(selectButton_A.state instanceof Number)
        iSelect = (selectButton_A.state as Number).intValue
    switch(iSelect) {
        case 1: {
            Auswahl_1.sendCommand(receivedCommand)
        }
        case 2: {
            Auswahl_2.sendCommand(receivedCommand)
        }
        case 3: {
            Auswahl_3.sendCommand(receivedCommand)
        }
        case 4: {
            Auswahl_4.sendCommand(receivedCommand)
        }
        case 5: {
            Auswahl_5.sendCommand(receivedCommand)
        }
        case 6: {
            Auswahl_6.sendCommand(receivedCommand)
        }
        case 7: {
            Auswahl_7.sendCommand(receivedCommand)
        }
        default: {
            logWarn("tasterA","Ungültige Auswahl: {}",selectButton_A.state)
        }
    }
end
Danke für die Switch() Syntax. Das hatte ich vor kurzem gesucht und nichts gefunden. Klammer anstatt break; immer mal wieder was anderes.. :lol:

Mops
Beiträge: 17
Registriert: 7. Aug 2020 11:52

Re: Umgang mit Rules

Beitrag von Mops »

Vielen Dank. Das hat funktioniert. Ich bin überrascht, was man alles mit OpenHAB machen kann.

Gibt es auch eine Möglichkeit, dem Glastaster mitzuteilen, dass eine Lampe über die BasicUI ein bzw. ausgeschaltet wurde?
Ich würde das wieder über eine Rule machen und sagen, wenn das Item für die Lampe ON empfängt, dann sende ON ebenfalls an den Taster. Das Funktioniert natürlich noch nicht, da OpenHAB bei dem Item "switch-control" ja als Aktor arbeitet.

Kann man die Taste dennoch irgendwie ansteuern und eventuell in einem weiteren Schritt auch das Display verändern?

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Umgang mit Rules

Beitrag von udo1toni »

Selbstverständlich funktioniert die Rückmeldung an den Taster :) Das Problem ist nur: Du bekommst lediglich den Zustand des gerade ausgewählten Lichts. Nutze dafür postUpdate (!).

Wo ich gerade drüber nachdenke, kannst Du aber auch eine kleine Rule verwenden, um jeweils den Status der gerade ausgewählten Leuchte anzuzeigen.

Code: Alles auswählen

rule "Taster A"
when
    Item Taster_A received command
then
    var Integer iSelect = 0
    if(selectButton_A.state instanceof Number)
        iSelect = (selectButton_A.state as Number).intValue
    switch(iSelect) {
        case 1: {
            Auswahl_1.sendCommand(receivedCommand)
        }
        case 2: {
            Auswahl_2.sendCommand(receivedCommand)
        }
        case 3: {
            Auswahl_3.sendCommand(receivedCommand)
        }
        case 4: {
            Auswahl_4.sendCommand(receivedCommand)
        }
        case 5: {
            Auswahl_5.sendCommand(receivedCommand)
        }
        case 6: {
            Auswahl_6.sendCommand(receivedCommand)
        }
        case 7: {
            Auswahl_7.sendCommand(receivedCommand)
        }
        default: {
            logWarn("tasterA","Ungültige Auswahl: {}",selectButton_A.state)
        }
    }
    if(iSelect > 0 && iSelect < 8) // falls gültiger Zeiger
        Taster_A.postUpdate(receivedCommand.toString) // setze Status des Items gemäß empfangenen Befehl 
end

rule "Taster A Selection changed"
when
    Item selectButton_A changed
then
    var Integer iSelect = 0
    if(selectButton_A.state instanceof Number)
        iSelect = (selectButton_A.state as Number).intValue
    switch(iSelect) {
        case 1: {
            Taster_A.postUpdate(Auswahl_1.state)
        }
        case 2: {
            Taster_A.postUpdate(Auswahl_2.state)
        }
        case 3: {
            Taster_A.postUpdate(Auswahl_3.state)
        }
        case 4: {
            Taster_A.postUpdate(Auswahl_4.state)
        }
        case 5: {
            Taster_A.postUpdate(Auswahl_5.state)
        }
        case 6: {
            Taster_A.postUpdate(Auswahl_6.state)
        }
        case 7: {
            Taster_A.postUpdate(Auswahl_7.state)
        }
        default: {
            logWarn("tasterAselect","Ungültige Auswahl: {}",selectButton_A.state)
        }
    }
end
Es gibt übrigens noch eine weitere Möglichkeit, die die Rules erheblich kürzer macht, und das sind Gruppen. Damit die Zuordnung der Items hier funktioniert, muss der Name des Items die Indexzahl enthalten (das wäre im obigen Code schon der Fall)
Nehmen wir an, alle Items Auswahl_n befinden sich in der Gruppe gAuswahl, dann sähen die passenden Rules so aus:

Code: Alles auswählen

rule "Taster A"
when
    Item Taster_A received command
then
    var Integer iSelect = 0
    if(selectButton_A.state instanceof Number)
        iSelect = (selectButton_A.state as Number).intValue
    if(iSelect < 1 || iSelect > 7) {                                                                          // falls ungültiger Zeiger
        logWarn("tasterA","Ungültige Auswahl: {}",selectButton_A.state)
        return;                                                                                               // Abbruch der Rule
    }
    Taster_A.postUpdate(receivedCommand.toString)                                                             // setze Status des Tasters gemäß empfangenen Befehl 
    gAuswahl.members.filter[i|i.name.split("_").get(1) == iSelect.toString].head.sendCommand(receivedCommand)
end

rule "Taster A Selection changed"
when
    Item selectButton_A changed
then
    var Integer iSelect = 0
    if(selectButton_A.state instanceof Number)
        iSelect = (selectButton_A.state as Number).intValue
    if(iSelect < 1 || iSelect > 7) {                                                                          // falls ungültiger Zeiger
        logWarn("tasterAselection","Ungültige Auswahl: {}",selectButton_A.state)
        return;                                                                                               // Abbruch der Rule
    }
    Taster_A.postUpdate(gAuswahl.members.filter[i|i.name.split("_").get(1) == iSelect.toString].head.state)   // setze Status des Tasters gemäß gewählter Leuchte
end
Das zu schaltende Item bzw. der zu erfragende Status wird aus der Gruppe anhand des Namens herausgefiltert. Es bleibt eine Liste von Items mit einem Eintrag übrig.
Das erste Item dieser Liste wird verwendet (das ist dann ein Item, keine Liste von Items)

Wenn Du Deine Items anders benannt hast, reicht es, die Indexzahl irgendwo im Namen einzubauen, abgetrennt mit den Unterstrichen. Wichtig ist dabei, dass die Indexzahl jeweils an der gleichen Stelle steht (im obigen Beispiel an Position 2, da der Index der durch .split() erzeugten Liste 0-basiert ist, muss man 1 abziehen. .get(1) liefert also den 2. Teilstring)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Mops
Beiträge: 17
Registriert: 7. Aug 2020 11:52

Re: Umgang mit Rules

Beitrag von Mops »

Also die Anzeige des Displays hat vorher schon funktioniert. Immer, wenn ich einen Taster gedrückt habe, wurde das auf dem Display angezeigt. ETS seitig programmiert.

Code: Alles auswählen

rule "Taster A Selection changed"
when
    Item selectButton_A changed
then
    var Integer iSelect = 0
    if(selectButton_A.state instanceof Number)
        iSelect = (selectButton_A.state as Number).intValue
    switch(iSelect) {
        case 1: {
            Taster_A.postUpdate(Auswahl_1.state)
        }
        
Die Rule tut doch nur etwas, wenn man die Tasterauswahl betätigt. Bleibt also unberührt, wenn in der UI etwas betätigt wird, oder irre ich mich da?
Ich habe dann mal folgendes selber probiert:

Code: Alles auswählen

rule "Status"
when Item Rott changed or Item Gelb_LI changed or Item Gelb_RE changed or Item Gruen_LI changed or Item Gruen_RE changed or Item Soccets changed

then
var Integer a_select = 0
if(selectButton_A.state instanceof Number)
        a_select = (selectButton_A.state as Number).intValue

var Integer b_select = 0
if(selectButton_B.state instanceof Number)
        b_select = (selectButton_B.state as Number).intValue

var Integer c_select = 0
if(selectButton_C.state instanceof Number)
        c_select = (selectButton_C.state as Number).intValue

var Integer d_select = 0
if(selectButton_D.state instanceof Number)
        d_select = (selectButton_D.state as Number).intValue

var Integer e_select = 0
if(selectButton_E.state instanceof Number)
        e_select = (selectButton_E.state as Number).intValue

var Integer f_select = 0     
if(selectButton_F.state instanceof Number)
        f_select = (selectButton_F.state as Number).intValue


if (a_select ==1 ) Glastaster_A.postUpdate(Rott.state.toString)
  if (b_select ==1 ) Glastaster_B.postUpdate(Rott.state.toString) 
  if (c_select ==1 ) Glastaster_C.postUpdate(Rott.state.toString)
  if (d_select ==1 ) Glastaster_D.postUpdate(Rott.state.toString)
  if (e_select ==1 ) Glastaster_E.postUpdate(Rott.state.toString)
  if (f_select ==1 ) Glastaster_F.postUpdate(Rott.state.toString)
  
  if (a_select ==2 ) Glastaster_A.postUpdate(Gelb_LI.state.toString)
   [...]
  
 
      
  end  
  
Das Funktioniert auch sehr gut mit anderen Kommandos zwecks Ausprobieren. Nur postUpdate(Rott.state.toString) möchte noch nicht. Das Tasterdisplay bleibt davon unberührt.



"

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Umgang mit Rules

Beitrag von udo1toni »

Ich verstehe jetzt nicht so ganz, worauf Du hinaus willst.
Oder vielleicht doch (jetzt):

Du hast mehrere Glastaster.
Du hast im Glastaster eine Auswahlmöglichkeit (von 1 bis 7)
Du hast im Glastaster eine Taste.
Du hast im Glastaster eine Anzeige, welche die Auswahl anzeigen soll.
Du hast im Glastaster eine Anzeige, ob der Taster gerade aktiv ist oder nicht.

So korrekt?

Dann solltest Du folgendes tun:
1. Die Auswahlitems in eine Gruppe
2. Die Taster in eine Gruppe
3. Die Rückmeldeitems für die jeweilige Funktion in eine Gruppe
Die zueinander gehörenden Items müssen jeweils voneinander ableitbar sein.

Über eine Rule steuerst Du alle Auswahlen. Dabei triggert die Rule auf Member of GroupItem changed. Die Rule sorgt dafür, dass das passende Rückmeldeitem den passenden Text bekommt und der Taster auf den passenden Status gesetzt wird.

Eine zweite Rule kümmert sich um alle Taster. Sie sorgt dafür, dass der Tastendruck abhängig vom passenden Auswahlitem beim richtigen Gerät landet.
Wenn man die Rule geschickt gestaltet, ist diese Rule trotz mehr zu steuernden Geräten (die Taster müssen ja unterschiedliche Ziele steuern können) nicht wesentlich größer.

Beide Rules triggern jeweils auf ein einzelnes Ereignis, welches aber von unterschiedlichen Quellen stammen kann. Die Rules wissen, von welcher Quelle der Trigger stammt und ändern nur die Anzeige der Quelle.


Gesendet von iPad mit Tapatalk
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Mops
Beiträge: 17
Registriert: 7. Aug 2020 11:52

Re: Umgang mit Rules

Beitrag von Mops »

Ich habe einen Glastaster mit 6 Tasten. In der Mitte befindet sich ein Display. Darauf ist zurzeit für jede Taste eine Glühlampe zu sehen mit Beschriftung. In ETS habe ich es so eingestellt, dass die Glühlampe bei ON gelb ist und bei OFF grau. Das funktioniert mit OpenHAB auch sehr gut zusammen. Man drückt einene Taste und das Symbol wird gelb bzw. grau.

Mein Problem ist jetzt, dass ich die Leuchten ebenfalls über die UI schalte und dann sollen die Symbole auch entsprechend mit machen.
Zusätzlich kann man ja jetzt in der UI festlegen, welche Taste welche Leuchte steuern soll. Wenn also eine Auswahl getroffen worden ist, soll die zugehörige Beschriftung auch auf dem Tasterdisplay neben der entsprechenden Taste erscheinen.

Antworten