2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-07 12:58:13 +00:00

98_cloneDummy: Erweiterung addAtateFormat, Fehlerbeseitigun bei mehrfachreadings

git-svn-id: https://svn.fhem.de/fhem/trunk@5919 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
joachim09876 2014-05-21 05:03:48 +00:00
parent f4cb153bdc
commit ea0c197c1b

View File

@ -1,89 +1,107 @@
# $Id$ # $Id$
############################################## ################################################################################
# 98_cloneDummy # 98_cloneDummy
# Von Joachim Herold # Von Joachim Herold
# FHEM Modul um aus Events von FHEM2FHEM clone-Devices zu erstellen # FHEM Modul um aus Events von FHEM2FHEM clone-Devices zu erstellen
# cloneDummy ist "readonly" # cloneDummy ist "readonly"
# Grundlage ist 98_dummy.pm von Rudolf Koenig # Grundlage ist 98_dummy.pm von Rudolf Koenig
# von betateilchen gab es viel Hilfe (eigentlich wars betateilchen) # von betateilchen gab es viel Hilfe (eigentlich wars betateilchen)
# mit Erweiterungenen von gandy
#
# Anleitung: # Anleitung:
# Um die Änderung zu nutzen, einfach einen cloneDummy anlegen # Um cloneDummy zu nutzen, einfach einen cloneDummy anlegen
# #
# Eintrag in der fhem.cfg: # Eintrag in der fhem.cfg:
# define <name> cloneDummy <quellDevice> [reading] # define <name> cloneDummy <quellDevice> [reading]
# attr <name> cloneIgnore <reading1,reading2,...,readingX> # attr <name> cloneIgnore <reading1,reading2,...,readingX>
# attr <name> addStateEvent 1 (0 ist Vorgabe)
# #
############################################# #
################################################################################
package main; package main;
use strict; use strict;
use warnings; use warnings;
################################################################################
# Initialisierung des Moduls
################################################################################
sub cloneDummy_Initialize($) { sub cloneDummy_Initialize($) {
my ($hash) = @_; my ($hash) = @_;
$hash->{DefFn} = "cloneDummy_Define"; $hash->{DefFn} = "cloneDummy_Define";
$hash->{NotifyFn} = "cloneDummy_Notify"; $hash->{NotifyFn} = "cloneDummy_Notify";
$hash->{AttrList} = "cloneIgnore ".$readingFnAttributes; $hash->{AttrList} = "cloneIgnore "
."addStateEvent:0,1 "
.$readingFnAttributes;
} }
################################################################################
# Definition des Moduls
################################################################################
sub cloneDummy_Define($$) { sub cloneDummy_Define($$) {
my ($hash, $def) = @_; my ($hash, $def) = @_;
my @a = split("[ \t][ \t]*", $def); my @a = split("[ \t][ \t]*", $def);
return "Wrong syntax: use define <name> cloneDummy <sourceDevice> [reading]" if((int(@a) < 3 || int(@a) > 4)) ;
return "Error: cloneDummy and sourceDevice must not have the same name!" if($a[0] eq $a[2]); return "Wrong syntax: use define <name> cloneDummy <sourceDevice> [reading]"
my $hn = $hash->{NAME}; if((int(@a) < 3 || int(@a) > 4)) ;
$hash->{NOTIFYDEV} = $a[2];
$hash->{NOTIFYSTATE} = $a[3] if(defined($a[3])); return "Error: cloneDummy and sourceDevice must not have the same name!"
$attr{$hn}{stateFormat} = "_state" if(defined($a[3])); if($a[0] eq $a[2]);
readingsSingleUpdate($hash,'state','defined',1);
Log3($hash,4,"cloneDummy: $a[0] defined for source $a[2]"); my $hn = $hash->{NAME};
return undef; $hash->{NOTIFYDEV} = $a[2];
$hash->{NOTIFYSTATE} = $a[3] if(defined($a[3]));
$attr{$hn}{stateFormat} = "_state" if(defined($a[3]));
readingsSingleUpdate($hash,'state','defined',1);
Log3($hash,4,"cloneDummy: $a[0] defined for source $a[2]");
return undef;
} }
################################################################################
# auslesen der Daten aus der globalen Schleife und aufbereiten der Daten
################################################################################
sub cloneDummy_Notify($$) { sub cloneDummy_Notify($$) {
my ($hash, $dev) = @_; my ($hash, $dev) = @_;
my $dn = $dev->{NAME}; my $dn = $dev->{NAME}; # Devicename
my $hn = $hash->{NAME}; my $hn = $hash->{NAME}; # Quellname
my $hs = ""; my $hs = ""; # optionales reading fuer STATE
if(defined($hash->{NOTIFYSTATE})) { my $events = deviceEvents($dev, AttrVal($hn, "addStateEvent", 0)); # Quellevents
$hs = $hash->{NOTIFYSTATE}; my $max = int(@{$events}); # Anzahl Quellevents
} if(defined($hash->{NOTIFYSTATE})) {
my $reading = $dev->{CHANGED}[0]; $hs = $hash->{NOTIFYSTATE};
$reading = "" if(!defined($reading)); }
Log3($hash,4, "cloneDummy: $hash D: $dn R: $reading");
my ($rname,$rval) = split(/ /,$reading,2); readingsSingleUpdate($hash,"state", "active",1);
$rname = substr($rname,0,length($rname)-1); readingsBeginUpdate($hash);
my %check = map { $_ => 1 } split(/,/,AttrVal($hn,'cloneIgnore',''));
for(my $i=0;$i<$max;$i++){
# When more than one FHEM2FHEM instance is used to tap into RF traffic, my $reading = $events->[$i]; # Quellevents in einzelne Readings ueberfuehren
# we may get duplicate readings for the same sensor information. $reading = "" if(!defined($reading));
# Use CheckDuplicate to prevent multiple events in this case. Log3($hash,4, "cloneDummy: $hash D: $dn R: $reading");
# my ($rname,$rval) = split(/ /,$reading,2); # zerlegen des Quellevents in Name und Wert
# Currently, clonedummy accepts a device name rather than a REGEXP, so $rname = substr($rname,0,length($rname)-1);
# we can assume that all duplicates will have the same device name my %check = map { $_ => 1 } split(/,/,AttrVal($hn,'cloneIgnore','')); # vorbereitung cloneIgnore
# (rather than different IODEV names as is the case with other modules) my ($isdup, $idx) = CheckDuplicate("", "$hn: $reading", undef); # vorbereitung doppelte Readings entfernen
# - so we ned to leave empty the first parameter for CheckDuplicate()
# if ($isdup) { # doppelte Readings filtern
# If cloneDummy should be changed to accepting more than one device, we Log3 $hash, 4, "cloneDummy: drop duplicate <$dn> <$hn> <$reading> ***";
# will may want to adapt the call to CheckDuplicate. } else {
my ($isdup, $idx) = CheckDuplicate("", "$hn: $reading", undef); Log3 $hash, 4, "cloneDummy: publish unique <$dn> <$hn> <$reading>";
if ($isdup) {
Log3 $hash, 4, "cloneDummy: drop duplicate <$dn> <$hn> <$reading> ***"; if (($hs ne "") && ($rname eq $hs) ){ # Reading in _state einsetzen
} else { readingsBulkUpdate($hash,"_state", $reading);
Log3 $hash, 4, "cloneDummy: publish unique <$dn> <$hn> <$reading>"; }
readingsBeginUpdate($hash); unless (exists ($check{$rname})) { # zu ignorierende Reading filtern
if (($hs ne "") && ($rname eq $hs) ){ readingsBulkUpdate($hash, $rname, $rval);
readingsBulkUpdate($hash,"_state", $reading); }
} }
readingsBulkUpdate($hash,"state", "active"); }
unless (exists ($check{$rname})) {
readingsBulkUpdate($hash, $rname, $rval); readingsEndUpdate($hash, 1);
}
readingsEndUpdate($hash, 1); return;
}
return;
} }
1; 1;
@ -93,51 +111,59 @@ sub cloneDummy_Notify($$) {
<a name="cloneDummy"></a> <a name="cloneDummy"></a>
<h3>cloneDummy</h3> <h3>cloneDummy</h3>
<ul> <ul>This module provides a cloneDummy which will receive readings from any other device sending data
This module provides a cloneDummy which will receive readings from any other device sending data to fhem.<br/> to fhem.<br>
E.g. may be used in an FHEM2FHEM environment. E.g. may be used in an FHEM2FHEM environment. Duplicate source events which may occur within the
Duplicate source events which may occur within the time given by the global attribute <a href="#dupTimeout">dupTimeout</a>, time given by the global attribute <a href="#dupTimeout">dupTimeout</a>, will be suppressed in order
will be suppressed in order to avoid overhead. The value of this attribute is to be changed with great care, as it to avoid overhead. The value of this attribute is to be changed with great care, as it affects other
affects other parts of FHEM, too. parts of FHEM, too.<br>
<br/> the order of precedence for STATE is following:
<br/> <ul><li>if there is no parameter preset then state of cloneDummy (initialized,active)</li>
<li>if addStateEvent is set then the "state" of cloned Device is set
<a name="cloneDummydefine"></a> (no "state" from cloneDummy)</li>
<b>Define</b> <li>if the optional reading is set in define, then value of the optional reading.
<ul> (this will overstrike the previous two lines)</li>
<code>define &lt;cloneDevice&gt; cloneDummy &lt;sourceDevice&gt; [reading]</code> <li>if stateFormat set ass attr, it will dominate all previous lines</li>
<br/> </ul>
<br/> <br><a name="cloneDummydefine"></a>
Example:<br/> <b>Define</b>
<br/> <ul><code>define &lt;cloneDevice&gt; cloneDummy &lt;sourceDevice&gt; [reading]</code><br>
<ul><code>define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000</code></ul> <br>Example:<br>
<br/> <br>
Optional parameter [reading] will be written to STATE if provided.<br/> <ul><code>define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000</code>
<br/> </ul>
Example:<br/> <br>Optional parameter [reading] will be written to STATE if provided.<br>
<br/> <br>Example:<br>
<ul><code>define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000 temperature</code></ul> <br>
</ul> <ul><code>define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000 temperature</code>
<br/> </ul>
<br>
<a name="cloneDummyset"></a> </ul>
<b>Set</b> <ul>N/A</ul> <a name="cloneDummyset"></a>
<br/> <b>Set</b>
<ul>N/A
<a name="cloneDummyget"></a> </ul>
<b>Get</b> <ul>N/A</ul> <br>
<br/> <a name="cloneDummyget"></a>
<b>Get</b>
<a name="cloneDummyattr"></a> <ul>N/A
<b>Attributes</b> </ul>
<ul> <br>
<li><a href="#readingFnAttributes"><b>readingFnAttributes</b></a></li> <a name="cloneDummyattr"></a>
<li><b>cloneIgnore</b> - comma separated list of readingnames that will NOT be generated.<br/> <b>Attributes</b>
Usefull to prevent truncated readingnames coming from state events.</li> <ul><li>addStateEvent
</ul> <br>When paremeter in Modul is set to 1 the originalstate of the original Device will be STATE
<br/> (Momentarily not possible in Connection with FHEM2FHEM)</li>
<b>Important: You MUST use different names for cloneDevice and sourceDevice!</b><br/> <br>
</ul> <li>cloneIgnore
<br>- comma separated list of readingnames that will NOT be generated.<br>
Usefull to prevent truncated readingnames coming from state events.</li>
<br>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
<br>
<b>Important: You MUST use different names for cloneDevice and sourceDevice!</b><br>
</ul>
=end html =end html
@ -145,49 +171,68 @@ sub cloneDummy_Notify($$) {
<a name="cloneDummy"></a> <a name="cloneDummy"></a>
<h3>cloneDummy</h3> <h3>cloneDummy</h3>
<ul> <ul>Definiert einen Klon eines lokalen Devices oder von FHEM2FHEM im Logmodus uebergebenen Devices
Definiert einen Clon eines Devices oder von FHEM2FHEM im Logmodus uebergebenen Devices und uebernimmt dessen Readings. und uebernimmt dessen Readings. Sinnvoll um entfernte FHEM-Installationen lesend einzubinden,
Sinnvoll um entfernte FHEM-Installationen lesend einzubinden, zum Testen oder Programmieren. zum Testen oder Programmieren. Dabei werden die von FHEM2FHEM in Form von Events weitergereichten
Dabei werden die von FHEM2FHEM in Form von Events weitergereichten entfernten Device-Readings in eigene Readings übernommen. entfernten Device-Readings in eigene Readings übernommen. Identische Events, die innerhalb der
Identische Events, die innerhalb der durch das globale Attribut <a href="#dupTimeout">dupTimeout</a> vorgegebenen Zeit auftreten, durch das globale Attribut <a href="#dupTimeout">dupTimeout</a> vorgegebenen Zeit auftreten, werden
werden zusammengefasst, um überflüssige Events zu verhindern. Dieses Attribut ist mit bedacht zu ändern, da sich seine Auswirkungen zusammengefasst, um überflüssige Events zu verhindern. Dieses Attribut ist mit bedacht zu ändern,
auch auf andere Bereiche von FHEM erstreckt. da sich seine Auswirkungen auch auf andere Bereiche von FHEM erstreckt.<br>
<br><br> Die Rangfolge für den STATE ist:
<ul><li>wenn keine Vorgabe gemacht wurde, dann die Meldung von cloneDummy (initialized, active)</li>
<a name="cloneDummydefine"></a> <li>wenn addStateEvent gesetzt ist, dann der "state" vom geklonten Device (dann kein "state" mehr
<b>Define</b> vom cloneDummy)</li>
<ul> <li>wenn das optionale reading im define gesetzt ist, dann der Wert davon (überstimmt die beiden
<code>define &lt;name&gt; cloneDummy &lt;Quelldevice&gt; [reading]</code> vorherigen Zeilen)</li>
<br><br> <li>wenn stateFormat als attr gesetzt ist, toppt das alles</li>
Aktiviert den cloneDummy, der dann an das Device &lt;Quelldevice&gt; gebunden ist. Mit dem optionalen Parameter reading </ul>
wird bestimmt, welches reading im STATE angezeigt wird, stateFormat ist auch weiterhin möglich. <br>
<ul> <a name="cloneDummydefine"></a>
Beispiel: Der cloneDummy wird lesend an den Sensor OWX_26_09FF26010000 gebunden und zeigt im State temperature an. <b>Define</b>
</ul> <ul><code>define &lt;name&gt; cloneDummy &lt;Quelldevice&gt; [reading]</code><br>
<br>
<ul> Aktiviert den cloneDummy, der dann an das Device &lt;Quelldevice&gt; gebunden ist.
<code>define Feuchte cloneDummy OWX_26_09FF26010000 temperature</code><br> Mit dem optionalen Parameter reading wird bestimmt, welches reading im STATE angezeigt wird,
</ul> stateFormat ist auch weiterhin möglich.<br>
</ul> <br>
<br> <ul>Beispiel:<br>
<br>
<a name="cloneDummyset"></a> Der cloneDummy wird lesend an den Sensor OWX_26_09FF26010000 gebunden und zeigt im
<b>Set</b> <ul>N/A</ul><br> State temperature an.<br>
<br>
<a name="cloneDummyget"></a> <ul><code>define Feuchte cloneDummy OWX_26_09FF26010000 temperature</code><br>
<b>Get</b> <ul>N/A</ul><br> </ul>
</ul>
<a name="cloneDummyattr"></a> </ul>
<b>Attributes</b> <br>
<ul> <a name="cloneDummyset"></a>
<li>clonIgnore<br> <b>Set</b>
Eine durch Kommata getrennte Liste der readings, die cloneDummy nicht in eigene readings umwandelt <ul>N/A
</li><br> </ul>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li> <br>
</ul> <a name="cloneDummyget"></a>
<br> <b>Get</b>
<b>Wichtig: Es müssen unterschiedliche Namen für &lt;name&gt; und &lt;Quelldevice&gt; verwendet werden!</b><br/> <ul>N/A
</ul> </ul>
<br>
<a name="cloneDummyattr"></a>
<b>Attributes</b>
<ul>
<li>addStateEvent<br>
0 ist Vorgabe im Modul, bei 1 wird der Originalstate des original Devices als STATE verwendet
(geht z.Z. nicht in Verbindung mit FHEM2FHEM)</li>
<br>
<li>clonIgnore<br>
Eine durch Kommata getrennte Liste der readings, die cloneDummy nicht in eigene readings
umwandelt</li>
<br>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
<br>
<b>Wichtig: Es müssen unterschiedliche Namen für &lt;name&gt; und &lt;Quelldevice&gt; verwendet
werden!</b><br/>
<br>
</ul>
=end html_DE =end html_DE