2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 12:49:34 +00:00

userReadings trigger added, code partially from Andre

git-svn-id: https://svn.fhem.de/fhem/trunk@3190 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2013-05-17 18:16:54 +00:00
parent 0258d0c84f
commit 680a785275
4 changed files with 102 additions and 52 deletions

View File

@ -1,7 +1,9 @@
# Add changes at the top of the list. Keep it in ASCII # Add changes at the top of the list. Keep it in ASCII
- SVN - SVN
- feature: userReadings may have a filter
- feature: HUEBridge: allow starting of bridge firmware update - 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: - feature: TCM: new attr blockSenderID:
Block receiving telegrams with a TCM SenderID sent by repeaters Block receiving telegrams with a TCM SenderID sent by repeaters
- feature: TCM: For TCM120 Transceiver now the transmission of RPS and 4BS - feature: TCM: For TCM120 Transceiver now the transmission of RPS and 4BS

View File

@ -396,29 +396,47 @@ A line ending with \ will be concatenated with the next one, so long lines
<a name="userReadings"></a> <a name="userReadings"></a>
<li>userReadings<br> <li>userReadings<br>
A comma-separated list of definitions of user-defined readings. Each definition has the form A comma-separated list of definitions of user-defined readings. Each
<code>&lt;reading&gt; [&lt;modifier&gt;] { &lt;perl code&gt; }</code>. After a single or bulk definition has the form:
readings update, the user-defined readings are set by evaluating the <a href="#perl"> <ul>
perl code</a> <code>
<code>{ &lt;perl code&gt; }</code> for all definitions and setting the value of &lt;reading&gt;[:&lt;trigger&gt;] [&lt;modifier&gt;] { &lt;perl code&gt; }
the respective user-defined reading <code>&lt;reading&gt;</code> to the result.<br><br> </code>
Examples:<br> </ul>
<code>attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }</code><br> After a single or bulk readings update, the user-defined readings are set
<code>attr myMultiMeter userReadings energy1 { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; }, by evaluating the <a href="#perl">perl code</a><code> { &lt;perl code&gt;
energy2 { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; }</code> }</code> for all definitions and setting the value of the respective
<br><br> user-defined reading <code>&lt;reading&gt;</code> to the result. If
&lt;trigger&gt; is given, then all processing for this specific user
reading is only done if one of the just updated "reading: value"
combinations matches &lt;trigger&gt;, which is treated as a regexp.
<br>
Examples:<br>
<ul><code>
attr myEnergyMeter userReadings energy
{ ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }<br>
attr myMultiMeter userReadings
energy1:counters.A { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; },
energy2:counters.B { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; }
</code></ul>
<code>&lt;modifier&gt;</code> can take one of these values: <code>&lt;modifier&gt;</code> can take one of these values:
<ul> <ul>
<li>none: the same as it would not have been given at all.</li> <li>none: the same as it would not have been given at all.</li>
<li>difference: the reading is set to the difference between the current and the previously evaluated value.</li> <li>difference: the reading is set to the difference between the current
<li>differential: the reading is set to the difference between the current and the previously evaluated value divided and the previously evaluated value.</li>
by the time in seconds between the current and the previous evaluation. Granularity of time is one second. No <li>differential: the reading is set to the difference between the
value is calculated if the time past is below one second. Useful to calculate rates.</li> current and the previously evaluated value divided by the time in
</ul><br> 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.</li>
</ul>
Example:<br> Example:<br>
<code>attr myPowerMeter userReadings power differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0;; }</code><br><br> <ul><code>attr myPowerMeter userReadings power
Note: user readings with modifiers difference and differential store the calculated values internally. The user reading is differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0;; }
set earliest at the second evaluation. Beware of stale values when changing definitions! </code></ul>
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!
</li><br> </li><br>
</ul> </ul>
<br> <br>

View File

@ -398,31 +398,49 @@ Zeilen erstreckende Befehle, indem man keine \ am Zeilenende eingeben muss.</p>
<a name="userReadings"></a> <a name="userReadings"></a>
<li>userReadings<br> <li>userReadings<br>
A comma-separated list of definitions of user-defined readings. Each definition has the form Komma getrennte Liste von benutzerdefinierten Readings. Jede Definition hat
<code>&lt;reading&gt; [&lt;modifier&gt;] { &lt;perl code&gt; }</code>. After a single or bulk folgendes Format:
readings update, the user-defined readings are set by evaluating the <a href="#perl"> <ul><code>
perl code</a> &lt;reading&gt;[:&lt;trigger&gt;] [&lt;modifier&gt;] { &lt;perl code&gt; }
<code>{ &lt;perl code&gt; }</code> for all definitions and setting the value of </code></ul>
the respective user-defined reading <code>&lt;reading&gt;</code> to the result.<br><br> Diese benutzerdefinierte Readings werden bei jeder Aktualisierung der
Examples:<br> Ger&auml;tereadings gesetzt, indem das spezifizierte <a href="#perl">perl
<code>attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }</code><br> code</a> <code>{ &lt;perl code&gt; }</code> ausgef&uuml;hrt wird, und
<code>attr myMultiMeter userReadings energy1 { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; }, dessen Wert dem Reading zugewiesen wird.
energy2 { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; }</code>
<br><br> Falls &lt;trigger&gt; spezifiziert ist, dann findet diese Ausf&uuml;hrung
<code>&lt;modifier&gt;</code> can take one of these values: nur dann statt, falls einer der aktualisierten Readings dem regexp
&lt;trigger&gt; entspricht (matched). <br>
Beispiele:
<ul><code>
attr myEnergyMeter userReadings energy
{ ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }<br>
attr myMultiMeter userReadings
energy1:counters.A {ReadingsVal("myMultiMeter","counters.A",0)/1250.0},
energy2:counters.B {ReadingsVal("myMultiMeter","counters.B",0)/1250.0}
</code></ul>
<code>&lt;modifier&gt;</code> kann die folgenden Werte haben:
<ul> <ul>
<li>none: the same as it would not have been given at all.</li> <li>none: als ob man es gar nicht spezifiziert h&auml;tte.</li>
<li>difference: the reading is set to the difference between the current and the previously evaluated value.</li> <li>difference: das Reading wird auf die Differenz zw. dem aktuellen und
<li>differential: the reading is set to the difference between the current and the previously evaluated value divided dem vorherigen Wert gesetzt.</li>
by the time in seconds between the current and the previous evaluation. Granularity of time is one second. No <li>differential: das Reading wird auf die Differenz zw. dem aktuellen und
value is calculated if the time past is below one second. Useful to calculate rates.</li> dem vorherigen Wert, geteilt durch die Sekunden zw. der aktuellen Zeit
</ul><br> und der letzten Auswertung, sekundengenau. Kein Wert wird berechnet,
Example:<br> falls der Unterschied unter eine Sekunde liegt.
<code>attr myPowerMeter userReadings power differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0;; }</code><br><br> </li>
Note: user readings with modifiers difference and differential store the calculated values internally. The user reading is </ul>
set earliest at the second evaluation. Beware of stale values when changing definitions! Beispiel:
<ul><code>
attr myPowerMeter userReadings power differential
{ ReadingsVal("myPowerMeter","counters.A",0)/1250.0}
</code></ul>
Achtung: Falls difference oder differential spezifiziert ist, dann werden
f&uuml;r die Berechnung &auml;ltere Werte ben&ouml;tigt, d.h. der Wert wird
fr&uuml;hestens beim zweiten &Auml;nderung gesetzt.
</li><br> </li><br>
</ul> </ul>
<br> <br>

View File

@ -1459,7 +1459,6 @@ CommandDeleteAttr($$)
$a[0] = $sdev; $a[0] = $sdev;
if($a[1] eq "userReadings") { if($a[1] eq "userReadings") {
#Debug "Deleting userReadings for $sdev";
delete($defs{$sdev}{'.userReadings'}); delete($defs{$sdev}{'.userReadings'});
} }
@ -1868,26 +1867,32 @@ CommandAttr($$)
if($a[1] eq "userReadings") { if($a[1] eq "userReadings") {
my %userReadings; my %userReadings;
# myReading1 [modifier1] { codecodecode1 }, myReading2 [modifier2] { codecodecode2 }, ... # myReading1[:trigger1] [modifier1] { codecodecode1 }, ...
my $arg= $a[2]; 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*(.*))*$'; my $regexo= '^(' . $regexi . ')(,\s*(.*))*$';
#Debug "arg is $arg"; #Log 1, "arg is $arg";
while($arg =~ /$regexo/) { while($arg =~ /$regexo/) {
my $userReading= $2; my $userReading= $2;
my $modifier= $4 ? $4 : "none"; my $trigger= $3 ? $3 : undef;
my $perlCode= $5; my $modifier= $5 ? $5 : "none";
#Debug sprintf("userReading %s has perlCode %s with modifier %s",$userReading,$perlCode,$modifier); 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)) { if(grep { /$modifier/ } qw(none difference differential)) {
$trigger =~ s/^:// if($trigger);
$userReadings{$userReading}{trigger}= $trigger;
$userReadings{$userReading}{modifier}= $modifier; $userReadings{$userReading}{modifier}= $modifier;
$userReadings{$userReading}{perlCode}= $perlCode; $userReadings{$userReading}{perlCode}= $perlCode;
} else { } 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; $hash->{'.userReadings'}= \%userReadings;
} }
@ -2915,7 +2920,7 @@ addEvent($$)
sub sub
getInterfaces($) { getInterfaces($) {
my ($hash)= @_; my ($hash)= @_;
#Debug "getInterfaces(" . $hash->{NAME} .")= " . $hash->{internals}{interfaces}; #Debug "getInterfaces(" . $hash->{NAME} .")= ".$hash->{internals}{interfaces};
if(defined($hash->{internals}{interfaces})) { if(defined($hash->{internals}{interfaces})) {
return split(/:/, $hash->{internals}{interfaces}); return split(/:/, $hash->{internals}{interfaces});
} else { } else {
@ -3133,6 +3138,13 @@ readingsEndUpdate($$)
if(defined($hash->{'.userReadings'})) { if(defined($hash->{'.userReadings'})) {
my %userReadings= %{$hash->{'.userReadings'}}; my %userReadings= %{$hash->{'.userReadings'}};
foreach my $userReading (keys %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 $modifier= $userReadings{$userReading}{modifier};
my $perlCode= $userReadings{$userReading}{perlCode}; my $perlCode= $userReadings{$userReading}{perlCode};
my $oldvalue= $userReadings{$userReading}{value}; my $oldvalue= $userReadings{$userReading}{value};