diff --git a/fhem/CHANGED b/fhem/CHANGED index 03bd5b736..e94f45cd8 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,7 +1,9 @@ # Add changes at the top of the list. Keep it in ASCII - SVN + - feature: userReadings may have a filter - feature: HUEBridge: allow starting of bridge firmware update - - change: EnOcean: profil PM101 changed, old profiles FAH, FBH, FTF, SR04 removed + - change: EnOcean: profil PM101 changed, old profiles FAH, FBH, FTF, SR04 + removed - feature: TCM: new attr blockSenderID: Block receiving telegrams with a TCM SenderID sent by repeaters - feature: TCM: For TCM120 Transceiver now the transmission of RPS and 4BS diff --git a/fhem/docs/commandref_frame.html b/fhem/docs/commandref_frame.html index d8e100879..5e14ea9a5 100644 --- a/fhem/docs/commandref_frame.html +++ b/fhem/docs/commandref_frame.html @@ -396,29 +396,47 @@ A line ending with \ will be concatenated with the next one, so long lines
  • userReadings
    - A comma-separated list of definitions of user-defined readings. Each definition has the form - <reading> [<modifier>] { <perl code> }. After a single or bulk - readings update, the user-defined readings are set by evaluating the - perl code - { <perl code> } for all definitions and setting the value of - the respective user-defined reading <reading> to the result.

    - Examples:
    - attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }
    - attr myMultiMeter userReadings energy1 { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; }, - energy2 { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; } -

    + A comma-separated list of definitions of user-defined readings. Each + definition has the form: + + After a single or bulk readings update, the user-defined readings are set + by evaluating the perl code { <perl code> + } for all definitions and setting the value of the respective + user-defined reading <reading> to the result. If + <trigger> is given, then all processing for this specific user + reading is only done if one of the just updated "reading: value" + combinations matches <trigger>, which is treated as a regexp. +
    + Examples:
    + <modifier> can take one of these values:
    +
  • difference: the reading is set to the difference between the current + and the previously evaluated value.
  • +
  • differential: the reading is set to the difference between the + current and the previously evaluated value divided by the time in + seconds between the current and the previous evaluation. Granularity + of time is one second. No value is calculated if the time past is + below one second. Useful to calculate rates.
  • + Example:
    - attr myPowerMeter userReadings power differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0;; }

    - Note: user readings with modifiers difference and differential store the calculated values internally. The user reading is - set earliest at the second evaluation. Beware of stale values when changing definitions! + + Note: user readings with modifiers difference and differential store the + calculated values internally. The user reading is set earliest at the + second evaluation. Beware of stale values when changing definitions!

    diff --git a/fhem/docs/commandref_frame_DE.html b/fhem/docs/commandref_frame_DE.html index a0f50dc13..138f0d4f5 100644 --- a/fhem/docs/commandref_frame_DE.html +++ b/fhem/docs/commandref_frame_DE.html @@ -398,31 +398,49 @@ Zeilen erstreckende Befehle, indem man keine \ am Zeilenende eingeben muss.

  • userReadings
    - A comma-separated list of definitions of user-defined readings. Each definition has the form - <reading> [<modifier>] { <perl code> }. After a single or bulk - readings update, the user-defined readings are set by evaluating the - perl code - { <perl code> } for all definitions and setting the value of - the respective user-defined reading <reading> to the result.

    - Examples:
    - attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }
    - attr myMultiMeter userReadings energy1 { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; }, - energy2 { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; } -

    - <modifier> can take one of these values: + Komma getrennte Liste von benutzerdefinierten Readings. Jede Definition hat + folgendes Format: + + Diese benutzerdefinierte Readings werden bei jeder Aktualisierung der + Gerätereadings gesetzt, indem das spezifizierte perl + code { <perl code> } ausgeführt wird, und + dessen Wert dem Reading zugewiesen wird. + + Falls <trigger> spezifiziert ist, dann findet diese Ausführung + nur dann statt, falls einer der aktualisierten Readings dem regexp + <trigger> entspricht (matched).
    + Beispiele: + + <modifier> kann die folgenden Werte haben:
    - Example:
    - attr myPowerMeter userReadings power differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0;; }

    - Note: user readings with modifiers difference and differential store the calculated values internally. The user reading is - set earliest at the second evaluation. Beware of stale values when changing definitions! +
  • none: als ob man es gar nicht spezifiziert hätte.
  • +
  • difference: das Reading wird auf die Differenz zw. dem aktuellen und + dem vorherigen Wert gesetzt.
  • +
  • differential: das Reading wird auf die Differenz zw. dem aktuellen und + dem vorherigen Wert, geteilt durch die Sekunden zw. der aktuellen Zeit + und der letzten Auswertung, sekundengenau. Kein Wert wird berechnet, + falls der Unterschied unter eine Sekunde liegt. +
  • + + Beispiel: + + Achtung: Falls difference oder differential spezifiziert ist, dann werden + für die Berechnung ältere Werte benötigt, d.h. der Wert wird + frühestens beim zweiten Änderung gesetzt.
    +
    diff --git a/fhem/fhem.pl b/fhem/fhem.pl index 7872029d4..4f4cf5681 100755 --- a/fhem/fhem.pl +++ b/fhem/fhem.pl @@ -1459,7 +1459,6 @@ CommandDeleteAttr($$) $a[0] = $sdev; if($a[1] eq "userReadings") { - #Debug "Deleting userReadings for $sdev"; delete($defs{$sdev}{'.userReadings'}); } @@ -1868,26 +1867,32 @@ CommandAttr($$) if($a[1] eq "userReadings") { my %userReadings; - # myReading1 [modifier1] { codecodecode1 }, myReading2 [modifier2] { codecodecode2 }, ... + # myReading1[:trigger1] [modifier1] { codecodecode1 }, ... my $arg= $a[2]; - my $regexi= '\s*(\w+)\s+((\w+)\s+)?({.*?})\s*'; # matches myReading1 { codecode1 } + # matches myReading1[:trigger2] { codecode1 } + my $regexi= '\s*(\w+)(:\S*)?\s+((\w+)\s+)?({.*?})\s*'; my $regexo= '^(' . $regexi . ')(,\s*(.*))*$'; - #Debug "arg is $arg"; + #Log 1, "arg is $arg"; while($arg =~ /$regexo/) { my $userReading= $2; - my $modifier= $4 ? $4 : "none"; - my $perlCode= $5; - #Debug sprintf("userReading %s has perlCode %s with modifier %s",$userReading,$perlCode,$modifier); + my $trigger= $3 ? $3 : undef; + my $modifier= $5 ? $5 : "none"; + my $perlCode= $6; + #Log 1, sprintf("userReading %s has perlCode %s with modifier %s%s", + # $userReading,$perlCode,$modifier,$trigger?" and trigger $trigger":""); if(grep { /$modifier/ } qw(none difference differential)) { + $trigger =~ s/^:// if($trigger); + $userReadings{$userReading}{trigger}= $trigger; $userReadings{$userReading}{modifier}= $modifier; $userReadings{$userReading}{perlCode}= $perlCode; } else { - push @rets, "$sdev: unknown modifier $modifier for userReading $userReading, this userReading will be ignored"; + push @rets, "$sdev: unknown modifier $modifier for ". + "userReading $userReading, this userReading will be ignored"; } - $arg= defined($7) ? $7 : ""; + $arg= defined($8) ? $8 : ""; } $hash->{'.userReadings'}= \%userReadings; } @@ -2915,7 +2920,7 @@ addEvent($$) sub getInterfaces($) { my ($hash)= @_; - #Debug "getInterfaces(" . $hash->{NAME} .")= " . $hash->{internals}{interfaces}; + #Debug "getInterfaces(" . $hash->{NAME} .")= ".$hash->{internals}{interfaces}; if(defined($hash->{internals}{interfaces})) { return split(/:/, $hash->{internals}{interfaces}); } else { @@ -3133,6 +3138,13 @@ readingsEndUpdate($$) if(defined($hash->{'.userReadings'})) { my %userReadings= %{$hash->{'.userReadings'}}; foreach my $userReading (keys %userReadings) { + + my $trigger = $userReadings{$userReading}{trigger}; + if(defined($trigger)) { + my @fnd = grep { $_ && $_ =~ m/^$trigger/ } @{$hash->{CHANGED}}; + next if(!@fnd); + } + my $modifier= $userReadings{$userReading}{modifier}; my $perlCode= $userReadings{$userReading}{perlCode}; my $oldvalue= $userReadings{$userReading}{value};