Leuchte Dimmen via Rule | Conbee II mit FoH Wandtaster

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Antworten
neuling10
Beiträge: 56
Registriert: 26. Mär 2022 18:15

Leuchte Dimmen via Rule | Conbee II mit FoH Wandtaster

Beitrag von neuling10 »

Hallo Leute,

ich habe vor kurzem meine beiden Hue Bridges gegen den Phoscon Conbee II getauscht. Zur lokalen Steuerung des Lichts nutze ich FoH Senic Enocean Taster. Die Tasterbelegung hätte ich gerne vollumfänglich über die Phoscon App gelöst. Mein Plan für die Tasterbelegung ist folgende:
Kurzer Druck oben: Abwechselnd An/Aus
Langer Druck oben: Dimmen - Helligkeit erhöhen
Kurzer Druck unten: Szenen durchschalten
Langer Druck unten: Dimmen - Helligkeit verringern

Leider lässt sich in der Phoscon App Dimmen nicht separat auf "langen Tastendruck" zuweisen (nur in Kombination mit kurzem Tastendruck für An/Aus). Nun wäre meine Überlegung, Dimmen via Openhab Rule und Script zu steuern, um obige Wunsch-Tasterbelegung realisieren zu können. Folgende Überlegung:
Wenn Channel "Schaltfläche" von Thing "FoH Taster" den Wert "3003" für langen Tastendruck empfängt, dann erhöhe solange die Helligkeit (Brightness (Dimmer)) mit INCREASE, bis Helligkeit =100 oder bis Channel "Letzte Aktualisierung" von Thing "FoH Taster" upgedatet wurde mit neuem Zeitstempel (entspricht dem Zeitpunkt des Loslassens der Tasterwippe).

In vielen hier nachzulesenden Rules zum Thema Dimmen wurde das mit Timern gelöst. Benötige ich denn auch einen Timer, wenn ich die Helligkeit in Schritten erhöhen möchte, bis der Channel "Letzte Aktualisierung" upgedatet wird? Könnte man das mit einer Repeat Until - Do Schleife lösen?

Meine Rule mit Blockly Skript sieht aktuell folgendermaßen aus:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: Arbeitszimmer__Arbeitszimmer_PhilipsFoH_Schaltflache
      state: "3003"
    type: core.ItemStateUpdateTrigger
conditions: []
actions:
  - inputs: {}
    id: "4"
    configuration:
      blockSource: <xml xmlns="https://developers.google.com/blockly/xml"><block
        type="controls_whileUntil" id="k6.Uvk~L(A=:)kt0AIZL" x="219"
        y="201"><field name="MODE">UNTIL</field><value name="BOOL"><block
        type="oh_item" id="R^8YrA=fX%sus^YMBm[,"><field
        name="itemName">Arbeitszimmer__Arbeitszimmer_PhilipsFoH_Letzte_Aktualisierung</field></block></value><statement
        name="DO"><block type="controls_if" id="g,(nN{Uv?$`q4Q7NkUTB"><value
        name="IF0"><block type="logic_compare" id="h_3M3Ckp/%f*9j8ivu;B"><field
        name="OP">LT</field><value name="A"><block type="oh_item"
        id="Qs8|*W$u=GQFiXTg+[Y4"><field
        name="itemName">Arbeitszimmer_Leuchte_1_WA_E27_Helligkeit</field></block></value><value
        name="B"><block type="math_number" id="UGs`%w1,A.|g-2k8WhRq"><field
        name="NUM">100</field></block></value></block></value><statement
        name="DO0"><block type="oh_event" id="Wit9yWA6t7mt9V*,!EvO"><field
        name="eventType">sendCommand</field><value name="value"><shadow
        type="text" id="^kOm+(peM9q?qyi=`d{["><field
        name="TEXT">INCREASE</field></shadow></value><value
        name="itemName"><shadow type="oh_item" id="DBJ)jG7hE?{x`cL,Yo.0"><field
        name="itemName">Arbeitszimmer_Leuchte_1_WA_E27_Helligkeit</field></shadow></value></block></statement></block></statement></block></xml>
      type: application/vnd.openhab.dsl.rule
      script: >
        while (!'Arbeitszimmer__Arbeitszimmer_PhilipsFoH_Letzte_Aktualisierung')
        {
          if ('Arbeitszimmer_Leuchte_1_WA_E27_Helligkeit' < 100) {
            events.sendCommand('Arbeitszimmer_Leuchte_1_WA_E27_Helligkeit', 'INCREASE');
          }
        }
    type: script.ScriptAction
Was mir unklar ist:
- Welchen Command muss ich in der Zeile

Code: Alles auswählen

while (!'Arbeitszimmer__Arbeitszimmer_PhilipsFoH_Letzte_Aktualisierung')
angeben, um die Schleife bis zum nächsten Update des Channels Arbeitszimmer__Arbeitszimmer_PhilipsFoH_Letzte_Aktualisierung durchlaufen zu lassen?
- Kann das Skript so funktionieren oder habe ich noch weitere grundlegende Fehler in der Überlegung/im Skript?

Danke Euch!

Grüße
neuling10

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

Re: Leuchte Dimmen via Rule | Conbee II mit FoH Wandtaster

Beitrag von udo1toni »

Das Problem ist zweigeteilt.

Erst mal die Sache, warum Timer und kein while + Thread.sleep. Das ist zunächst ein Stück weit historisch begründet. Unter openHAB < 3 (also bis incl. 2.5.12) geb es genau fünf plus zwei Threads für alle Rules (wobei zwei für den Scheduler reserviert waren, alles, was über Time cron und createTimer() ausgeführt wurde; die genaue Anzahl war auch parametrierbar, aber 5+2 reicht selbst in großen Installationen gewöhnlich aus.)
Was unterm Strich bedeutet, dass eine Rule möglichst kurz laufen muss, da sonst die Wahrscheinlichkeit steigt, dass andere Rules nicht ausgeführt werden können.
Erschwerend kam noch hinzu, dass eine Rule auch durchaus mehrfach ausgeführt werden konnte, eine einzige (un-) geschickt programmierte Rule konnte also die gesamte Rule Engine auslasten und so alle anderen Rules blockieren.

Mit openHAB3 hat jetzt jede Rule ihren eigenen Thread, das heißt, eine Rule kann nicht mehr mehrfach gleichzeitig ausgeführt werden (was durchaus erwünscht sein kann, muss man im Hinterkopf behalten), aber dafür ist auch garantiert, dass jede Rule zu jedem Zeitpunkt ausgeführt werden kann.
Es ist also nun nicht mehr so kritisch, Thread.sleep() mit längeren Zeiten zu nutzen. Trotz desto nichts ist es natürlich immer guter Stil, soweit möglich auf erzwungene NOPs zu verzichten (das macht Thread.sleep()) :)

Die andere Sache sind die Trigger. Du startest eine Rule über das Drücken der Taste. Dann arbeitet diese Rule "endlos". Beim Loslassen muss die Rule abbrechen. Es ist aber nicht vorgesehen, eine Rule mit einem Trigger zu stoppen. Stattdessen wird nun also eine zweite Rule gestartet, die die erste Rule auf irgendeinem Weg anhält.
Und es muss tatsächlich zwingend eine zweite Rule her, denn wir erinnern uns an das oben geschriebene... Eine Rule hat exakt einen Thread und kann kein zweites Mal während der Ausführung gestartet werden.

Vor diesem Hintergrund erscheint es äußerst fragwürdig, eine while-Schleife zu verwenden. Wir brauchen zwingend ein Zeit-Element, wir brauchen zwingend einen unabhängigen Thread, beides bekommen wir mit createTimer() umsonst. Eine passende Rule (DSL Style):

Code: Alles auswählen

rule "dimmer"
when
    Item Taster received command // siehe Text!
then
    if(receivedCommand == PRESSED)
        // start timer
    else if (receivedCommand == RELEASED)
        // stop timer
end
Die eine Rule kümmert sich nun sowohl um das Drücken als auch um das Loslassen des Tasters. Welcher Trigger dafür infrage kommt, kommt auf das Binding an. Es gibt natürlic hauch keinen Status PRESSED oder RELEASED, das muss also angepasst werden.

Der Timer selbst besteht aus dem Code, um den Wert zu verändern und aus dem Code, um sich selbst erneut zu starten.
Der Witz dabei: Die Rule kann sich um das Dimmen aufwärts und abwärts kümmern, selbst wenn es sich um zwei unterschiedliche Trigger handelt, denn die Rule kann unterscheiden, welcher Trigger ausgelöst hat, also Taste 1 oder Taste 2, gedrückt oder losgelassen.
Im Zusammenhang mit dem Timer kann sich die Rule sogar darum kümmern, auch noch die kurzen Tastendrücke auszuwerten. Dazu braucht es lediglich eine Variable, welche im Timer selbst gesetzt wird. In der Rule muss beim Erkennen des Release nur geprüft werden, ob die Variable bereits gesetzt ist. Ist das nicht der Fall, so handelt es sich um einen kurzen, ansonsten um einen langen Tastendruck. Beim Loslassen wird also einfach der Timer abgerochen und die Variable geprüft. Ist sie gesetzt, wird die Variable gelöscht (für das nächste Mal) und die Rule ist beendet. Ist die nicht gesetzt wird stattdessen das Toggle oder eben die Szene ausgeführt, abhängig vom Trigger.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Antworten