FS20 Toggle Events auf On/Off umsetzen: Unterschied zwischen den Versionen

Aus FHEMWiki
(Anpassung von <source>-Tags nach <syntaxhighlight>)
 
(5 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt)
Zeile 9: Zeile 9:
'''Diese Funktion ist seit 10/2012 Bestandteil der fhem-Standardauslieferung. Sie liegt in 99_Utils.pm und heisst UntoggleDirect($)'''
'''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.  
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.
Danach fhem mit dem Befehl 'shutdown' beenden und dann NEU STARTEN.


=== Code ===
=== Code ===
<nowiki>sub UntoggleDirect($) {
<syntaxhighlight lang="perl">sub UntoggleDirect($) {
  my ($obj) = @_;
  my ($obj) = @_;
  if (Value($obj) eq "toggle"){
  if (Value($obj) eq "toggle"){
Zeile 27: Zeile 27:
   {fhem "setstate ".$obj." ".Value($obj)}
   {fhem "setstate ".$obj." ".Value($obj)}
  }  
  }  
}</nowiki>
}</syntaxhighlight>
 
=== Aufruf ===
=== Aufruf ===
  <nowiki>define &lt;name&gt; notify &lt;Sensor&gt; {UntoggleDirect("&lt;Sensor&gt;")}</nowiki>
  <nowiki>define &lt;name&gt; notify &lt;Sensor&gt; {UntoggleDirect("&lt;Sensor&gt;")}</nowiki>
Um nicht für jedes device ein separates notify anlegen zu müssen, gibt es folgende Möglichkeit:
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 (<code>attr &lt;device&gt; comment Untoggle</code>)
* Je relevantem device das Attribute "comment" mit dem Wert "Untoggle" setzen (<code>attr &lt;device&gt; comment Untoggle</code>)
* Nur ein notify anlegen, das wie folgt aussieht:
* Nur ein notify anlegen, das wie folgt aussieht:
  <nowiki>define n_Untoggle notify .*:toggle {UntoggleDirect("$NAME") if( AttrVal($NAME, "comment", "") eq "Untoggle" )}</nowiki>
  <nowiki>define n_1Untoggle notify .*:toggle {UntoggleDirect("$NAME") if( AttrVal($NAME, "comment", "") eq "Untoggle" )}</nowiki>


== Hinweise ==
== Hinweise ==
* Der &lt;Sensor&gt; muss sich anfangs einmal im state ON oder OFF befnden.
* Der &lt;Sensor&gt; 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 [http://fhem.de/commandref.html#FHEMWEB]
* 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 [http://fhem.de/commandref.html#FHEMWEB]
* 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 ===
=== 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 '''on'''und 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.
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 '''on'''und 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 [[#Version_f.C3.BCr_indirekte_Kopplung_von_Sender_und_Aktor|''Untoggle''-Version für indirekte Kopplung]] verbessert werden.
Die Statusabfrage ist daher nicht besonders zuverlässig. Die Zuverlässigkeit kann durch eine [[#Version für indirekte Kopplung von Sender und Aktor|''Untoggle''-Version für indirekte Kopplung]] verbessert werden.


== Version für indirekte Kopplung von Sender und Aktor ==
== Version für indirekte Kopplung von Sender und Aktor ==
Zeile 48: Zeile 51:
Bei dieser Version triggert der Sender lediglich den Untoggle-Befehl, der seinerseits den Aktor auf '''on'''oder '''off'''schaltet. 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.
Bei dieser Version triggert der Sender lediglich den Untoggle-Befehl, der seinerseits den Aktor auf '''on'''oder '''off'''schaltet. 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 [http://culfw.de/commandref.html#misc 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.)
Allerdings [http://culfw.de/commandref.html#misc 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($$$)'''
'''Diese Routine ist seit 10/2012 Bestandteil der fhem-Standardauslieferung. Sie liegt in 99_Utils.pm und heisst UntoggleIndirect($$$)'''


=== Code ===
=== Code ===
  <nowiki>sub UntoggleIndirect($;$;$)
  <syntaxhighlight lang="perl">sub UntoggleIndirect($;$;$)
{
{
  my ($sender, $actor, $dimvalue) = @_;
  my ($sender, $actor, $dimvalue) = @_;
Zeile 75: Zeile 78:
  else {fhem ("set ".$actor." ".Value($sender))}
  else {fhem ("set ".$actor." ".Value($sender))}
  return;
  return;
}</nowiki>
}</syntaxhighlight>
=== Aufruf ===
=== Aufruf ===
  <nowiki>define &lt;name&gt; notify &lt;Sender&gt; {UntoggleIndirect("&lt;Sender&gt;","&lt;Aktor&gt;","&lt;Dimm_Wert&gt;")}</nowiki>
  <nowiki>define &lt;name&gt; notify &lt;Sender&gt; {UntoggleIndirect("&lt;Sender&gt;","&lt;Aktor&gt;","&lt;Dimm_Wert&gt;")}</nowiki>
Beim Dimm-Wert ist zu beachten, dass „%“ als Variable interpretiert wird, so dass stattdessen „%%“ anzugeben ist.


Beispiel:
Beispiel:


  <nowiki>define Wohnzimmerlampe_PAIR notify Wohnzimmerlampe_SENDER {UntoggleIndirect("Wohnzimmerlampe_SENDER","Wohnzimmerlampe","dim12%%")}</nowiki>
  <nowiki>define Wohnzimmerlampe_PAIR notify Wohnzimmerlampe_SENDER {UntoggleIndirect("Wohnzimmerlampe_SENDER","Wohnzimmerlampe","dim12%")}</nowiki>


[[Kategorie:Code Snippets]]
[[Kategorie:Code Snippets]]

Aktuelle Version vom 26. Juli 2017, 18:57 Uhr

  • 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%")}