FS20 Toggle Events auf On/Off umsetzen

Aus FHEMWiki
Wechseln zu: Navigation, Suche
  • Situation: Ein Wandschalter (z.B. FS20 S4 A), der so belegt ist, dass jede Taste einen einzelnen Kanal schaltet.
  • Problem: Der Schalter sendet toggle events aus, die zwar an einen Empfänger weitergeleitet werden können, allerdings kann man dann nicht abfragen, ob der Empfänger (z.B. FS20 ST) an oder aus ist.
  • Lösung: Das toggle event auf on oder off umsetzen:


Version für direkte Kopplung von Sender und Aktor

Implementierung

Diese Funktion ist seit 10/2012 Bestandteil der fhem-Standardauslieferung. Sie liegt in 99_Utils.pm und heisst UntoggleDirect($)

Ausserdem bedient sich Untoggle der neuen Funktionen Value() und OldValue(), die in FHEM mit der Version 5.1 bereitgestellt wurden.

Danach fhem mit dem Befehl 'shutdown' beenden und dann NEU STARTEN.

Code

sub UntoggleDirect($) {
 my ($obj) = @_;
 if (Value($obj) eq "toggle"){
  if (OldValue($obj) eq "off") {
   {fhem ("setstate ".$obj." on")}
  }
  else {
   {fhem ("setstate ".$obj." off")}
  }
 }
 else {
  {fhem "setstate ".$obj." ".Value($obj)}
 } 
}

Aufruf

define <name> notify <Sensor> {UntoggleDirect("<Sensor>")}

Um nicht für jedes Device ein separates notify anlegen zu müssen, gibt es folgende Möglichkeit:

  • Je relevantem device das Attribute "comment" mit dem Wert "Untoggle" setzen (attr <device> comment Untoggle)
  • Nur ein notify anlegen, das wie folgt aussieht:
define n_1Untoggle notify .*:toggle {UntoggleDirect("$NAME") if( AttrVal($NAME, "comment", "") eq "Untoggle" )}

Hinweise

  • Der <Sensor> muss sich anfangs einmal im state ON oder OFF befnden.
  • Die Änderung des Status nach toggle wird auf dem Webfrontend erst nach einem manuellen refresh (F5) sichtbar, sofern bei der Definition des fhemweb nicht der Parameter refresh angegeben ist, siehe [1]
  • Für die Abarbeitung des Untoggeln ist es wichtig, dass zuerst dieses notify läuft und danach alle weiteren, die den untoggelten Status auswerten wollen. Da laut DevelopmentGuidelines das Event von DoTrigger nacheinander an alle NotifyFn in der alphabetischen Reihenfolge der Gerätenamen gereicht wird, ist der Name des notify n_1* gewählt worden, um in der alphabetischen Reihenfolge ganz vorne zu stehen. Die Reihenfolge kann auch mit dem Befehl "list TYPE=notify" geprüft werden.

Mögliche Probleme

Der obige Code eignet sich nur für direkte Kopplung von Sender und Aktor, das heißt, der Sender steuert den Aktor direkt und FHEM „lauscht“ nur und protokolliert den Status, der sich aus dem toggle-Befehl ergibt. Sobald ein einziges Mal ein Fehler auftritt (das heißt nur entweder der Aktor oder FHEM empfangen den toggle-Befehl, der jeweils andere aber nicht), geht der synchrone Status dauerhaft verloren, das heißt, ab nun schaltet bei einem von Aktor und FHEM empfangenen toggle-Befehl jeweils einer der beiden in den Status onund der andere in den Status off. Dieser asnchrone Zustand wird erst behoben, wenn derselbe Fehler (nur entweder der Aktor oder FHEM empfangen den toggle-Befehl, der jeweils andere aber nicht) ein zweites Mal auftritt.

Die Statusabfrage ist daher nicht besonders zuverlässig. Die Zuverlässigkeit kann durch eine Untoggle-Version für indirekte Kopplung verbessert werden.

Version für indirekte Kopplung von Sender und Aktor

Implementierung

Bei dieser Version triggert der Sender lediglich den Untoggle-Befehl, der seinerseits den Aktor auf onoder offschaltet. Zwar kann auch in dieser Version die Synchronizität zwischen Aktor und FHEM-Status verloren gehen (wenn zwar FHEM den Sender-Befehl empfängt, aber der Aktor beim Empfang des als Konsequenz von FHEM gesendeten Befehls gestört ist), aber dieser Fehler wird mit dem nächsten ungestörten Steuerbefehl sofort wieder behoben, weil FHEM ja stets den zu seinem Status passenden Befehl an den Aktor sendet.

Allerdings funktioniert bei indirekter Kopplung zur Zeit das Dimmen von FS20-Aktoren nicht. Als Workaround setzt der folgende Code FS20-Dimm-Befehle so um, dass zu einer definierten Zwischenhelligkeit umgeschaltet wird, deren Wert als dritter Parameter an die Funktion übergeben wird (die verwendete Heuristik funktioniert allerdings nicht immer; siehe Kommentar im Code.)

Diese Routine ist seit 10/2012 Bestandteil der fhem-Standardauslieferung. Sie liegt in 99_Utils.pm und heisst UntoggleIndirect($$$)

Code

sub UntoggleIndirect($;$;$)
{
 my ($sender, $actor, $dimvalue) = @_;
 if (Value($sender) eq "toggle")
 {
  if (Value($actor) eq "off") {fhem ("set ".$actor." on")}
  else {fhem ("set ".$actor." off")}
 }
 ## workaround for dimming currently not working with indirect pairing
 ## ([http://culfw.de/commandref.html http://culfw.de/commandref.html]: "TODO/Known BUGS - FS20 dim commands should not repeat.")
 elsif (Value($sender) eq "dimup") {fhem ("set ".$actor." dim100%")}
 elsif (Value($sender) eq "dimdown") {fhem ("set ".$actor." ".$dimvalue)}
 elsif (Value($sender) eq "dimupdown")
 {
  if (Value($actor) eq $dimvalue) {fhem ("set ".$actor." dim100%")}
    ## Heuristic above doesn't work if lamp was dimmed, then switched off, then switched on, because state is "on", but the lamp is actually dimmed.
  else {fhem ("set ".$actor." ".$dimvalue)}
  sleep 1;
 }
 ## end of workaround
 else {fhem ("set ".$actor." ".Value($sender))}
 return;
}

Aufruf

define <name> notify <Sender> {UntoggleIndirect("<Sender>","<Aktor>","<Dimm_Wert>")}

Beispiel:

define Wohnzimmerlampe_PAIR notify Wohnzimmerlampe_SENDER {UntoggleIndirect("Wohnzimmerlampe_SENDER","Wohnzimmerlampe","dim12%")}