FS20 Toggle Events auf On/Off umsetzen: Unterschied zwischen den Versionen
(Anpassung von <source>-Tags nach <syntaxhighlight>) |
|||
(10 dazwischenliegende Versionen von 5 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
* '''Situation:''' | * '''Situation:''' Ein Wandschalter (z.B. [[FS20 S4A Aufputz Sender|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 | * '''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 Steckdosenfunkschalter|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 == | == Version für direkte Kopplung von Sender und Aktor == | ||
=== Implementierung === | === Implementierung === | ||
'''Diese | '''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 | 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 === | ||
<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)} | ||
} | } | ||
}</ | }</syntaxhighlight> | ||
=== Aufruf === | === Aufruf === | ||
<nowiki>define <name> notify <Sensor> {UntoggleDirect("<Sensor>")}</nowiki> | <nowiki>define <name> notify <Sensor> {UntoggleDirect("<Sensor>")}</nowiki> | ||
Um nicht für jedes | 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 <device> comment Untoggle</code>) | * Je relevantem device das Attribute "comment" mit dem Wert "Untoggle" setzen (<code>attr <device> comment Untoggle</code>) | ||
* Nur ein notify anlegen, das wie folgt aussieht: | * Nur ein notify anlegen, das wie folgt aussieht: | ||
<nowiki>define | <nowiki>define n_1Untoggle notify .*:toggle {UntoggleDirect("$NAME") if( AttrVal($NAME, "comment", "") eq "Untoggle" )}</nowiki> | ||
== Hinweise == | == Hinweise == | ||
* Der <Sensor> muss sich anfangs einmal im state ON oder OFF befnden. | * 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 [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 | 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 47: | 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 | 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($$$)''' | |||
=== Code === | === Code === | ||
< | <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; | ||
}</ | }</syntaxhighlight> | ||
=== Aufruf === | === Aufruf === | ||
<nowiki>define <name> notify <Sender> {UntoggleIndirect("<Sender>","<Aktor>","<Dimm_Wert>")}</nowiki> | <nowiki>define <name> notify <Sender> {UntoggleIndirect("<Sender>","<Aktor>","<Dimm_Wert>")}</nowiki> | ||
Beispiel: | Beispiel: | ||
<nowiki>define Wohnzimmerlampe_PAIR notify Wohnzimmerlampe_SENDER {UntoggleIndirect("Wohnzimmerlampe_SENDER","Wohnzimmerlampe","dim12 | <nowiki>define Wohnzimmerlampe_PAIR notify Wohnzimmerlampe_SENDER {UntoggleIndirect("Wohnzimmerlampe_SENDER","Wohnzimmerlampe","dim12%")}</nowiki> | ||
[[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%")}