2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 06:39:11 +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
- 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

View File

@ -396,29 +396,47 @@ A line ending with \ will be concatenated with the next one, so long lines
<a name="userReadings"></a>
<li>userReadings<br>
A comma-separated list of definitions of user-defined readings. Each definition has the form
<code>&lt;reading&gt; [&lt;modifier&gt;] { &lt;perl code&gt; }</code>. After a single or bulk
readings update, the user-defined readings are set by evaluating the <a href="#perl">
perl code</a>
<code>{ &lt;perl code&gt; }</code> for all definitions and setting the value of
the respective user-defined reading <code>&lt;reading&gt;</code> to the result.<br><br>
Examples:<br>
<code>attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }</code><br>
<code>attr myMultiMeter userReadings energy1 { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; },
energy2 { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; }</code>
<br><br>
A comma-separated list of definitions of user-defined readings. Each
definition has the form:
<ul>
<code>
&lt;reading&gt;[:&lt;trigger&gt;] [&lt;modifier&gt;] { &lt;perl code&gt; }
</code>
</ul>
After a single or bulk readings update, the user-defined readings are set
by evaluating the <a href="#perl">perl code</a><code> { &lt;perl code&gt;
}</code> for all definitions and setting the value of the respective
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:
<ul>
<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>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.</li>
</ul><br>
<li>difference: the reading is set to the difference between the current
and the previously evaluated value.</li>
<li>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.</li>
</ul>
Example:<br>
<code>attr myPowerMeter userReadings power differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0;; }</code><br><br>
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!
<ul><code>attr myPowerMeter userReadings power
differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0;; }
</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>
</ul>
<br>

View File

@ -398,31 +398,49 @@ Zeilen erstreckende Befehle, indem man keine \ am Zeilenende eingeben muss.</p>
<a name="userReadings"></a>
<li>userReadings<br>
A comma-separated list of definitions of user-defined readings. Each definition has the form
<code>&lt;reading&gt; [&lt;modifier&gt;] { &lt;perl code&gt; }</code>. After a single or bulk
readings update, the user-defined readings are set by evaluating the <a href="#perl">
perl code</a>
<code>{ &lt;perl code&gt; }</code> for all definitions and setting the value of
the respective user-defined reading <code>&lt;reading&gt;</code> to the result.<br><br>
Examples:<br>
<code>attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }</code><br>
<code>attr myMultiMeter userReadings energy1 { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; },
energy2 { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; }</code>
<br><br>
<code>&lt;modifier&gt;</code> can take one of these values:
Komma getrennte Liste von benutzerdefinierten Readings. Jede Definition hat
folgendes Format:
<ul><code>
&lt;reading&gt;[:&lt;trigger&gt;] [&lt;modifier&gt;] { &lt;perl code&gt; }
</code></ul>
Diese benutzerdefinierte Readings werden bei jeder Aktualisierung der
Ger&auml;tereadings gesetzt, indem das spezifizierte <a href="#perl">perl
code</a> <code>{ &lt;perl code&gt; }</code> ausgef&uuml;hrt wird, und
dessen Wert dem Reading zugewiesen wird.
Falls &lt;trigger&gt; spezifiziert ist, dann findet diese Ausf&uuml;hrung
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>
<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>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.</li>
</ul><br>
Example:<br>
<code>attr myPowerMeter userReadings power differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0;; }</code><br><br>
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>none: als ob man es gar nicht spezifiziert h&auml;tte.</li>
<li>difference: das Reading wird auf die Differenz zw. dem aktuellen und
dem vorherigen Wert gesetzt.</li>
<li>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.
</li>
</ul>
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>
</ul>
<br>

View File

@ -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};