diff --git a/fhem/FHEM/98_cloneDummy.pm b/fhem/FHEM/98_cloneDummy.pm index ace6eeaa4..99f63d43d 100644 --- a/fhem/FHEM/98_cloneDummy.pm +++ b/fhem/FHEM/98_cloneDummy.pm @@ -1,89 +1,107 @@ # $Id$ -############################################## +################################################################################ # 98_cloneDummy # Von Joachim Herold # FHEM Modul um aus Events von FHEM2FHEM clone-Devices zu erstellen # cloneDummy ist "readonly" # Grundlage ist 98_dummy.pm von Rudolf Koenig # von betateilchen gab es viel Hilfe (eigentlich wars betateilchen) +# mit Erweiterungenen von gandy +# # Anleitung: -# Um die Änderung zu nutzen, einfach einen cloneDummy anlegen +# Um cloneDummy zu nutzen, einfach einen cloneDummy anlegen # # Eintrag in der fhem.cfg: # define cloneDummy [reading] # attr cloneIgnore +# attr addStateEvent 1 (0 ist Vorgabe) # -############################################# +# +################################################################################ package main; use strict; use warnings; +################################################################################ +# Initialisierung des Moduls +################################################################################ sub cloneDummy_Initialize($) { - my ($hash) = @_; + my ($hash) = @_; - $hash->{DefFn} = "cloneDummy_Define"; - $hash->{NotifyFn} = "cloneDummy_Notify"; - $hash->{AttrList} = "cloneIgnore ".$readingFnAttributes; + $hash->{DefFn} = "cloneDummy_Define"; + $hash->{NotifyFn} = "cloneDummy_Notify"; + $hash->{AttrList} = "cloneIgnore " + ."addStateEvent:0,1 " + .$readingFnAttributes; } +################################################################################ +# Definition des Moduls +################################################################################ sub cloneDummy_Define($$) { - my ($hash, $def) = @_; - my @a = split("[ \t][ \t]*", $def); - return "Wrong syntax: use define cloneDummy [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]); - my $hn = $hash->{NAME}; - $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; + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + return "Wrong syntax: use define cloneDummy [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]); + + my $hn = $hash->{NAME}; + $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($$) { - my ($hash, $dev) = @_; - my $dn = $dev->{NAME}; - my $hn = $hash->{NAME}; - my $hs = ""; - if(defined($hash->{NOTIFYSTATE})) { - $hs = $hash->{NOTIFYSTATE}; - } - my $reading = $dev->{CHANGED}[0]; - $reading = "" if(!defined($reading)); - Log3($hash,4, "cloneDummy: $hash D: $dn R: $reading"); - my ($rname,$rval) = split(/ /,$reading,2); - $rname = substr($rname,0,length($rname)-1); - my %check = map { $_ => 1 } split(/,/,AttrVal($hn,'cloneIgnore','')); - - # When more than one FHEM2FHEM instance is used to tap into RF traffic, - # we may get duplicate readings for the same sensor information. - # Use CheckDuplicate to prevent multiple events in this case. - # - # Currently, clonedummy accepts a device name rather than a REGEXP, so - # we can assume that all duplicates will have the same device name - # (rather than different IODEV names as is the case with other modules) - # - so we ned to leave empty the first parameter for CheckDuplicate() - # - # If cloneDummy should be changed to accepting more than one device, we - # will may want to adapt the call to CheckDuplicate. - my ($isdup, $idx) = CheckDuplicate("", "$hn: $reading", undef); - if ($isdup) { - Log3 $hash, 4, "cloneDummy: drop duplicate <$dn> <$hn> <$reading> ***"; - } else { - Log3 $hash, 4, "cloneDummy: publish unique <$dn> <$hn> <$reading>"; - readingsBeginUpdate($hash); - if (($hs ne "") && ($rname eq $hs) ){ - readingsBulkUpdate($hash,"_state", $reading); - } - readingsBulkUpdate($hash,"state", "active"); - unless (exists ($check{$rname})) { - readingsBulkUpdate($hash, $rname, $rval); - } - readingsEndUpdate($hash, 1); - } - return; + my ($hash, $dev) = @_; + my $dn = $dev->{NAME}; # Devicename + my $hn = $hash->{NAME}; # Quellname + my $hs = ""; # optionales reading fuer STATE + my $events = deviceEvents($dev, AttrVal($hn, "addStateEvent", 0)); # Quellevents + my $max = int(@{$events}); # Anzahl Quellevents + if(defined($hash->{NOTIFYSTATE})) { + $hs = $hash->{NOTIFYSTATE}; + } + + readingsSingleUpdate($hash,"state", "active",1); + readingsBeginUpdate($hash); + + for(my $i=0;$i<$max;$i++){ + my $reading = $events->[$i]; # Quellevents in einzelne Readings ueberfuehren + $reading = "" if(!defined($reading)); + Log3($hash,4, "cloneDummy: $hash D: $dn R: $reading"); + my ($rname,$rval) = split(/ /,$reading,2); # zerlegen des Quellevents in Name und Wert + $rname = substr($rname,0,length($rname)-1); + my %check = map { $_ => 1 } split(/,/,AttrVal($hn,'cloneIgnore','')); # vorbereitung cloneIgnore + my ($isdup, $idx) = CheckDuplicate("", "$hn: $reading", undef); # vorbereitung doppelte Readings entfernen + + if ($isdup) { # doppelte Readings filtern + Log3 $hash, 4, "cloneDummy: drop duplicate <$dn> <$hn> <$reading> ***"; + } else { + Log3 $hash, 4, "cloneDummy: publish unique <$dn> <$hn> <$reading>"; + + if (($hs ne "") && ($rname eq $hs) ){ # Reading in _state einsetzen + readingsBulkUpdate($hash,"_state", $reading); + } + unless (exists ($check{$rname})) { # zu ignorierende Reading filtern + readingsBulkUpdate($hash, $rname, $rval); + } + } + } + + readingsEndUpdate($hash, 1); + + return; } 1; @@ -93,51 +111,59 @@ sub cloneDummy_Notify($$) {

cloneDummy

-
    - This module provides a cloneDummy which will receive readings from any other device sending data to fhem.
    - E.g. may be used in an FHEM2FHEM environment. - Duplicate source events which may occur within the time given by the global attribute dupTimeout, - will be suppressed in order to avoid overhead. The value of this attribute is to be changed with great care, as it - affects other parts of FHEM, too. -
    -
    - - - Define -
      - define <cloneDevice> cloneDummy <sourceDevice> [reading] -
      -
      - Example:
      -
      -
        define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000
      -
      - Optional parameter [reading] will be written to STATE if provided.
      -
      - Example:
      -
      -
        define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000 temperature
      -
    -
    - - - Set
      N/A
    -
    - - - Get
      N/A
    -
    - - - Attributes -
      -
    • readingFnAttributes
    • -
    • cloneIgnore - comma separated list of readingnames that will NOT be generated.
      - Usefull to prevent truncated readingnames coming from state events.
    • -
    -
    - Important: You MUST use different names for cloneDevice and sourceDevice!
    -
+
    This module provides a cloneDummy which will receive readings from any other device sending data + to fhem.
    + E.g. may be used in an FHEM2FHEM environment. Duplicate source events which may occur within the + time given by the global attribute dupTimeout, will be suppressed in order + to avoid overhead. The value of this attribute is to be changed with great care, as it affects other + parts of FHEM, too.
    + the order of precedence for STATE is following: +
    • if there is no parameter preset then state of cloneDummy (initialized,active)
    • +
    • if addStateEvent is set then the "state" of cloned Device is set + (no "state" from cloneDummy)
    • +
    • if the optional reading is set in define, then value of the optional reading. + (this will overstrike the previous two lines)
    • +
    • if stateFormat set ass attr, it will dominate all previous lines
    • +
    +
    + Define +
      define <cloneDevice> cloneDummy <sourceDevice> [reading]
      +
      Example:
      +
      +
        define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000 +
      +
      Optional parameter [reading] will be written to STATE if provided.
      +
      Example:
      +
      +
        define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000 temperature +
      +
      +
    + + Set +
      N/A +
    +
    + + Get +
      N/A +
    +
    + + Attributes +
    • addStateEvent +
      When paremeter in Modul is set to 1 the originalstate of the original Device will be STATE + (Momentarily not possible in Connection with FHEM2FHEM)
    • +
      +
    • cloneIgnore +
      - comma separated list of readingnames that will NOT be generated.
      + Usefull to prevent truncated readingnames coming from state events.
    • +
      +
    • readingFnAttributes
    • +
    +
    + Important: You MUST use different names for cloneDevice and sourceDevice!
    +
=end html @@ -145,49 +171,68 @@ sub cloneDummy_Notify($$) {

cloneDummy

-
    - Definiert einen Clon eines Devices oder von FHEM2FHEM im Logmodus uebergebenen Devices und uebernimmt dessen Readings. - Sinnvoll um entfernte FHEM-Installationen lesend einzubinden, zum Testen oder Programmieren. - Dabei werden die von FHEM2FHEM in Form von Events weitergereichten entfernten Device-Readings in eigene Readings übernommen. - Identische Events, die innerhalb der durch das globale Attribut dupTimeout vorgegebenen Zeit auftreten, - werden zusammengefasst, um überflüssige Events zu verhindern. Dieses Attribut ist mit bedacht zu ändern, da sich seine Auswirkungen - auch auf andere Bereiche von FHEM erstreckt. -

    - - - Define -
      - define <name> cloneDummy <Quelldevice> [reading] -

      - Aktiviert den cloneDummy, der dann an das Device <Quelldevice> gebunden ist. Mit dem optionalen Parameter reading - wird bestimmt, welches reading im STATE angezeigt wird, stateFormat ist auch weiterhin möglich. -
        - Beispiel: Der cloneDummy wird lesend an den Sensor OWX_26_09FF26010000 gebunden und zeigt im State temperature an. -
      - -
        - define Feuchte cloneDummy OWX_26_09FF26010000 temperature
        -
      -
    -
    - - - Set
      N/A

    - - - Get
      N/A

    - - - Attributes -
      -
    • clonIgnore
      - Eine durch Kommata getrennte Liste der readings, die cloneDummy nicht in eigene readings umwandelt -

    • -
    • readingFnAttributes
    • -
    -
    - Wichtig: Es müssen unterschiedliche Namen für <name> und <Quelldevice> verwendet werden!
    -
+
    Definiert einen Klon eines lokalen Devices oder von FHEM2FHEM im Logmodus uebergebenen Devices + und uebernimmt dessen Readings. Sinnvoll um entfernte FHEM-Installationen lesend einzubinden, + zum Testen oder Programmieren. Dabei werden die von FHEM2FHEM in Form von Events weitergereichten + entfernten Device-Readings in eigene Readings übernommen. Identische Events, die innerhalb der + durch das globale Attribut dupTimeout vorgegebenen Zeit auftreten, werden + zusammengefasst, um überflüssige Events zu verhindern. Dieses Attribut ist mit bedacht zu ändern, + da sich seine Auswirkungen auch auf andere Bereiche von FHEM erstreckt.
    + Die Rangfolge für den STATE ist: +
    • wenn keine Vorgabe gemacht wurde, dann die Meldung von cloneDummy (initialized, active)
    • +
    • wenn addStateEvent gesetzt ist, dann der "state" vom geklonten Device (dann kein "state" mehr + vom cloneDummy)
    • +
    • wenn das optionale reading im define gesetzt ist, dann der Wert davon (überstimmt die beiden + vorherigen Zeilen)
    • +
    • wenn stateFormat als attr gesetzt ist, toppt das alles
    • +
    +
    + + Define +
      define <name> cloneDummy <Quelldevice> [reading]
      +
      + Aktiviert den cloneDummy, der dann an das Device <Quelldevice> gebunden ist. + Mit dem optionalen Parameter reading wird bestimmt, welches reading im STATE angezeigt wird, + stateFormat ist auch weiterhin möglich.
      +
      +
        Beispiel:
        +
        + Der cloneDummy wird lesend an den Sensor OWX_26_09FF26010000 gebunden und zeigt im + State temperature an.
        +
        +
          define Feuchte cloneDummy OWX_26_09FF26010000 temperature
          +
        +
      +
    +
    + + Set +
      N/A +
    +
    + + Get +
      N/A +
    +
    + + Attributes +
      +
    • addStateEvent
      + 0 ist Vorgabe im Modul, bei 1 wird der Originalstate des original Devices als STATE verwendet + (geht z.Z. nicht in Verbindung mit FHEM2FHEM)
    • +
      +
    • clonIgnore
      + Eine durch Kommata getrennte Liste der readings, die cloneDummy nicht in eigene readings + umwandelt
    • +
      +
    • readingFnAttributes
    • +
    +
    + Wichtig: Es müssen unterschiedliche Namen für <name> und <Quelldevice> verwendet + werden!
    +
    +
=end html_DE