Regel effektiv gestalten

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

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

Re: Regel effektiv gestalten

Beitrag von udo1toni »

Um ein paar Randbedingungen zu klären: Du hast Pro Lampe drei Items. Ist es grundsätzlich nicht möglich, die Hue über das Dimmeritem zu schalten? Müssen die Items genau so benannt sein?

Eine Variante (wie immer ungetestet) wäre, Ein Group Item zu verwenden und die Itemnamen zu ändern:

Code: Alles auswählen

Group gLounge 
String Lampe_1_Alert  "" (gLounge)
String Lampe_2_Alert  "" (gLounge)
String Lampe_3_Alert  "" (gLounge)
Switch Lampe_1_Switch "Lounge 1" (gLounge)
Switch Lampe_2_Switch "Lounge 2" (gLounge)
Switch Lampe_3_Switch "Büro" (gLounge)
Dimmer Lampe_1_Dimmer "Lounge 1" (gLounge)
Dimmer Lampe_2_Dimmer "Lounge 2" (gLounge)
Dimmer Lampe_3_Dimmer "Büro" (gLounge)
Number LoungeLampeSelect
Es gibt also eine Gruppe, in der alle Items enthalten sind. Der erste Teil des Namens ist variabel, der zweite Teil ist jeweils pro Lampe identisch, der Dritte Teil des NAmens gibt den Zweck des Items an.

Nun sehen die Rules etwas anders aus:

Code: Alles auswählen

var int iSelect = 1

rule "vierte Taste lang" // Mit langem Tastendruck 4. Taste vom Dimmerswitch Lampe auswählen
when
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 4003.0
then
    iSelect += 1
    if (iSelect > 2) iSelect = 1          // Zahl entsprechend der Anzahl Lampen
    LoungeLampeSelect.postUpdate(Select)
end

rule "aktive Lampe blinken lassen"
when
    Item LoungeLampeSelect changed or                                  // Selektion geändert oder
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 4002.0 // kurzer Tastendruck vierte Taste
then
    gLounge.members.filter[g|g.name.contains("Alert")].filter[h|Integer::parseInt(h.name.split("_").get(1)) == iSelect].head.sendCommand("SELECT")
end

rule "erste Taste kurz" // Mit kurzen Tastendruck Taste 1 vom Dimmerswitch aktuell aktive Lampe anschalten/ausschalten
when
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 1002.0
then
    val myItem = gLounge.members.filter[g|g.name.contains("Switch")].filter[h|Integer::parseInt(h.name.split("_").get(1)) == iSelect].head
    myItem.sendCommand(if(myItem.state == OFF) ON else OFF)
end

rule "zweite Taste kurz" // Dimmen positiv mit kurzem Tastendruck Taste 2 Dimmerswitch
when
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 2002.0
then
    val myItem = gLounge.members.filter[g|g.name.contains("Dimmer")].filter[h|Integer::parseInt(h.name.split("_").get(1)) == iSelect].head
    var nDim = 5 + (if(myItem.state instanceof Number) (myItem.state as Number) else 0)
    if (nDim > 100) nDim = 100
    myItem.sendCommand(nDim)
end

rule "dritte Taste kurz" // Dimmen negativ mit kurzem Tastendruck Taste 3 vom Dimmerswitch
when
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 3002.0
then
    val myItem = gLounge.members.filter[g|g.name.contains("Dimmer")].filter[h|Integer::parseInt(h.name.split("_").get(1)) == iSelect].head
    var nDim = - 5 + (if(myItem.state instanceof Number) (myItem.state as Number) else 100)
    if (nDim < 0) nDim = 0
    myItem.sendCommand(nDim)
end
Ich habe im Code bewusst zwei verschiedene Arten des Zugriffs auf die Teilsrtings genutzt, um die Möglichkeiten anzureißen.

Die erste Rule arbeitet wie gehabt und zählt stur die globale Variable um 1 hoch. Sollte der Wert die Obergrenze überschreiten, wird die Untergrenze gesetzt.

Die zweite Rule triggert für die Wertänderung und den kurzen Tastendruck. Im Code wird nun das passende Item für die selektierte Lampe herausgesucht, dabei wird die globale Variable genutzt, nicht das Number Item. Vorteil ist, dass wir uns keine Gedanken über den Number Item machen müssen.

Die übrigen Rules verwenden jeweils den aktuellen Status des betreffenden Items, weshalb hier das Item zunächst in ein Objekt gepackt wird. Anschließend kann man mit diesem Objekt arbeiten, genauso, als wäre es ein gewöhnliches Item. Man muss nur auf den Typ achten.

Selbst dieser Code bietet vermutlich noch Spielraum für Verbesserungen :) Der Punkt ist aber, dass man die Rules nicht mehr ändern muss (bis auf die Anzahl der Lampen), die Rules können beliebig viele Lampen über den 4-fach Schalter steuern.

Mutmaßungen meinerseits: Falls der String nur dazu dient, die selektierte Lampe ein internes Programm abspielen zu lassen, welches zweimal toggelt, kann man stattdessen die Rule verwenden, um die Lampe gezielt zu toggeln. Falls man über das Dimmer Item die Lampen auch schalten kann, kann man auch noch auf die Switch Items verzichten.

Man lässt nun also die überflüssigen Items weg und deshalb auch die Typmarkierung. un sind ja nur noch Dimmer Items in der Gruppe. Nun kann die Rule sogar selbst bestimmen, für wieviele Lampen sie arbeiten soll.

Die Rules sähen dann so aus:

Code: Alles auswählen


var int iSelect = 1
var Timer tToggle = null
var nDimwert = 0

rule "vierte Taste lang" // Mit langem Tastendruck 4. Taste vom Dimmerswitch Lampe auswählen
when
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 4003.0
then
    iSelect += 1
    if (iSelect > gLounge.members.size) iSelect = 1          // Zahl entsprechend der Anzahl Lampen
    LoungeLampeSelect.postUpdate(Select)
end

rule "aktive Lampe blinken lassen"
when
    Item LoungeLampeSelect changed or                                  // Selektion geändert oder
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 4002.0 // kurzer Tastendruck
then
    val myItem = gLounge.members.filter[g|Integer::parseInt(g.name.split("_").get(1)) == iSelect].head
    nDimmwert = myItem.state as Number
    myItem.sendCommand(if(nDimmwert < 30) ON else OFF)
    tToggle?.cancel
    tToggle = createTimer(now.plusMillis(750),[
        val myItem = gLounge.members.filter[g|Integer::parseInt(g.name.split("_").get(1)) == iSelect].head
        myItem.sendCommand(nDimmwert)
    ])
end

rule "erste Taste kurz" // Mit kurzen Tastendruck Taste 1 vom Dimmerswitch aktuell aktive Lampe anschalten/ausschalten
when
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 1002.0
then
    val myItem = gLounge.members.filter[g|Integer::parseInt(g.name.split("_").get(1)) == iSelect].head
    myItem.sendCommand(if(myItem.getStateAs(OnOffType) == OFF) ON else OFF)
end

rule "zweite Taste kurz" // Dimmen positiv mit kurzem Tastendruck Taste 2 Dimmerswitch
when
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 2002.0
then
    val myItem = gLounge.members.filter[g|Integer::parseInt(g.name.split("_").get(1)) == iSelect].head
    val nDim = 5 + (if(myItem.state instanceof Number) (myItem.state as Number) else 0)
    if (nDim > 100) nDim = 100
    myItem.sendCommand(nDim)
end

rule "dritte Taste kurz" // Dimmen negativ mit kurzem Tastendruck Taste 3 vom Dimmerswitch
when
    Channel "hue:0820:1:dsLounge:dimmer_switch_event" triggered 3002.0
then
    val myItem = gLounge.members.filter[g|Integer::parseInt(g.name.split("_").get(1)) == iSelect].head
    val nDim = - 5 + (if(myItem.state instanceof Number) (myItem.state as Number) else 100)
    if (nDim < 0) nDim = 0
    myItem.sendCommand(nDim)
end
Ich habe den Code nicht gestestet :) also wird es wie immer Probleme damit geben... ;)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten