mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
modifiers for userReadings
git-svn-id: https://svn.fhem.de/fhem/trunk@2679 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
f09c7e91f3
commit
b1c0e6064f
@ -55,6 +55,7 @@
|
|||||||
OWFS
|
OWFS
|
||||||
- feature: stateFormat (readingsFn modules) and showInternalValues attributes
|
- feature: stateFormat (readingsFn modules) and showInternalValues attributes
|
||||||
- feature: new readingsFn modules: FS20 CUL_WS HMS CUL_EM CUL_TX EnOcean ZWave
|
- feature: new readingsFn modules: FS20 CUL_WS HMS CUL_EM CUL_TX EnOcean ZWave
|
||||||
|
- change: BS, USF1000, ECMDDevice, Weather, dummy migrated to readingsFN (Boris)
|
||||||
- feature: telnet client mode
|
- feature: telnet client mode
|
||||||
- bugfix: FHEMWEB longpoll misses initial state change (HM: set_on vs. on)
|
- bugfix: FHEMWEB longpoll misses initial state change (HM: set_on vs. on)
|
||||||
- change: 20_OWFS.pm, 21_OWTEMP modules flagged as "deprecated". These
|
- change: 20_OWFS.pm, 21_OWTEMP modules flagged as "deprecated". These
|
||||||
@ -66,8 +67,8 @@
|
|||||||
- feature: added new command 'notice'. (M. Fischer)
|
- feature: added new command 'notice'. (M. Fischer)
|
||||||
- change: update supports the display and confirmation of system messages
|
- change: update supports the display and confirmation of system messages
|
||||||
via the new notice command (M. Fischer)
|
via the new notice command (M. Fischer)
|
||||||
- change: BS, USF1000, dummy migrated to readingsFN (Boris)
|
|
||||||
- feature: added new set commands and basicauth to 49_IPCAM.pm (M. Fischer)
|
- feature: added new set commands and basicauth to 49_IPCAM.pm (M. Fischer)
|
||||||
|
- feature: userReadings
|
||||||
- feature: average supports more than one value in combined readings (T:x H:y)
|
- feature: average supports more than one value in combined readings (T:x H:y)
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,18 +384,30 @@ 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 user-defined readings. Each definition has the form
|
A comma-separated list of definitions of user-defined readings. Each definition has the form
|
||||||
<code><reading> { <perl code> }</code>. After a single or bulk
|
<code><reading> [<modifier>] { <perl code> }</code>. After a single or bulk
|
||||||
readings update, the user-defined readings are set by evaluating the <a href="#perl">
|
readings update, the user-defined readings are set by evaluating the <a href="#perl">
|
||||||
perl code</a>
|
perl code</a>
|
||||||
<code>{ <perl code> }</code> for all definitions and setting the value of
|
<code>{ <perl code> }</code> for all definitions and setting the value of
|
||||||
the respective user-defined reading <code><reading></code> to the result.<br><br>
|
the respective user-defined reading <code><reading></code> to the result.<br><br>
|
||||||
Examples:<br>
|
Examples:<br>
|
||||||
<code>attr myPowerMeter userReadings power { ReadingsVal("myPowerMeter","count.A",0)/1250.0;; }</code><br>
|
<code>attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }</code><br>
|
||||||
<code>attr myMultiMeter userReadings power1 { ReadingsVal("myMultiMeter","count.A",0)/1250.0;; },
|
<code>attr myMultiMeter userReadings energy1 { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; },
|
||||||
power2 { ReadingsVal("myMultiMeter","count.B",0)/1250.0;; }</code>
|
energy2 { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; }</code>
|
||||||
|
<br><br>
|
||||||
|
<code><modifier></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>
|
||||||
|
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><br>
|
</li><br>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
@ -394,16 +394,29 @@ 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 user-defined readings. Each definition has the form
|
A comma-separated list of definitions of user-defined readings. Each definition has the form
|
||||||
<code><reading> { <perl code> }</code>. After a single or bulk
|
<code><reading> [<modifier>] { <perl code> }</code>. After a single or bulk
|
||||||
readings update, the user-defined readings are set by evaluating the <a href="#perl">
|
readings update, the user-defined readings are set by evaluating the <a href="#perl">
|
||||||
perl code</a>
|
perl code</a>
|
||||||
<code>{ <perl code> }</code> for all definitions and setting the value of
|
<code>{ <perl code> }</code> for all definitions and setting the value of
|
||||||
the respective user-defined reading <code><reading></code> to the result.<br><br>
|
the respective user-defined reading <code><reading></code> to the result.<br><br>
|
||||||
Examples:<br>
|
Examples:<br>
|
||||||
<code>attr myPowerMeter userReadings power { ReadingsVal("myPowerMeter","count.A",0)/1250.0;; }</code><br>
|
<code>attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }</code><br>
|
||||||
<code>attr myMultiMeter userReadings power1 { ReadingsVal("myMultiMeter","count.A",0)/1250.0;; },
|
<code>attr myMultiMeter userReadings energy1 { ReadingsVal("myMultiMeter","counters.A",0)/1250.0;; },
|
||||||
power2 { ReadingsVal("myMultiMeter","count.B",0)/1250.0;; }</code>
|
energy2 { ReadingsVal("myMultiMeter","counters.B",0)/1250.0;; }</code>
|
||||||
|
<br><br>
|
||||||
|
<code><modifier></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>
|
||||||
|
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><br>
|
</li><br>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
50
fhem/fhem.pl
50
fhem/fhem.pl
@ -1809,24 +1809,28 @@ CommandAttr($$)
|
|||||||
if($a[1] eq "userReadings") {
|
if($a[1] eq "userReadings") {
|
||||||
|
|
||||||
my %userReadings;
|
my %userReadings;
|
||||||
|
# myReading1 [modifier1] { codecodecode1 }, myReading2 [modifier2] { codecodecode2 }, ...
|
||||||
# myReading1 { codecodecode1 }, myReading2 { codecodecode2 }, ...
|
|
||||||
my $arg= $a[2];
|
my $arg= $a[2];
|
||||||
|
|
||||||
my $regexi= '\s*(\w+)\s+({.*?})\s*'; # matches myReading1 { codecode1 }
|
my $regexi= '\s*(\w+)\s+((\w+)\s+)?({.*?})\s*'; # matches myReading1 { codecode1 }
|
||||||
my $regexo= '^(' . $regexi . ')(,\s*(.*))*$';
|
my $regexo= '^(' . $regexi . ')(,\s*(.*))*$';
|
||||||
|
|
||||||
#Debug "arg is $arg";
|
#Debug "arg is $arg";
|
||||||
|
|
||||||
while($arg =~ /$regexo/) {
|
while($arg =~ /$regexo/) {
|
||||||
my $userReading= $2;
|
my $userReading= $2;
|
||||||
my $perlCode= $3;
|
my $modifier= $4 ? $4 : "none";
|
||||||
#Debug sprintf("userReading %s has perlCode %s",$userReading,$perlCode);
|
my $perlCode= $5;
|
||||||
$userReadings{$userReading}= $perlCode;
|
#Debug sprintf("userReading %s has perlCode %s with modifier %s",$userReading,$perlCode,$modifier);
|
||||||
$arg= defined($5) ? $5 : "";
|
if(grep { /$modifier/ } qw(none difference differential)) {
|
||||||
|
$userReadings{$userReading}{modifier}= $modifier;
|
||||||
|
$userReadings{$userReading}{perlCode}= $perlCode;
|
||||||
|
} else {
|
||||||
|
push @rets, "$sdev: unknown modifier $modifier for userReading $userReading, this userReading will be ignored";
|
||||||
|
}
|
||||||
|
$arg= defined($7) ? $7 : "";
|
||||||
}
|
}
|
||||||
$hash->{fhem}{'.userReadings'}= \%userReadings;
|
$hash->{fhem}{'.userReadings'}= \%userReadings;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($a[1] eq "IODev" && (!$a[2] || !defined($defs{$a[2]}))) {
|
if($a[1] eq "IODev" && (!$a[2] || !defined($defs{$a[2]}))) {
|
||||||
@ -2990,6 +2994,7 @@ readingsBeginUpdate($)
|
|||||||
|
|
||||||
# get timestamp
|
# get timestamp
|
||||||
my $now = TimeNow();
|
my $now = TimeNow();
|
||||||
|
$hash->{".updateTime"} = time(); # in seconds since the epoch
|
||||||
$hash->{".updateTimestamp"} = $now;
|
$hash->{".updateTimestamp"} = $now;
|
||||||
|
|
||||||
my $attreocr= AttrVal($name, "event-on-change-reading", undef);
|
my $attreocr= AttrVal($name, "event-on-change-reading", undef);
|
||||||
@ -3053,19 +3058,42 @@ readingsEndUpdate($$)
|
|||||||
if(defined($hash->{fhem}{'.userReadings'})) {
|
if(defined($hash->{fhem}{'.userReadings'})) {
|
||||||
my %userReadings= %{$hash->{fhem}{'.userReadings'}};
|
my %userReadings= %{$hash->{fhem}{'.userReadings'}};
|
||||||
foreach my $userReading (keys %userReadings) {
|
foreach my $userReading (keys %userReadings) {
|
||||||
|
my $modifier= $userReadings{$userReading}{modifier};
|
||||||
|
my $perlCode= $userReadings{$userReading}{perlCode};
|
||||||
|
my $oldvalue= $userReadings{$userReading}{value};
|
||||||
|
my $oldt= $userReadings{$userReading}{t};
|
||||||
#Debug "Evaluating " . $userReadings{$userReading};
|
#Debug "Evaluating " . $userReadings{$userReading};
|
||||||
my $value= eval $userReadings{$userReading};
|
# evaluate perl code
|
||||||
|
my $value= eval $perlCode;
|
||||||
|
my $result;
|
||||||
|
# store result
|
||||||
if($@) {
|
if($@) {
|
||||||
$value = "Error evaluating $name userReading $userReading: $@";
|
$value = "Error evaluating $name userReading $userReading: $@";
|
||||||
Log 1, $value;
|
Log 1, $value;
|
||||||
}
|
$result= $value;
|
||||||
readingsBulkUpdate($hash,$userReading,$value,1);
|
} elsif($modifier eq "none") {
|
||||||
|
$result= $value;
|
||||||
|
} elsif($modifier eq "difference") {
|
||||||
|
$result= $value - $oldvalue if(defined($oldvalue));
|
||||||
|
} elsif($modifier eq "differential") {
|
||||||
|
my $deltav= $value - $oldvalue if(defined($oldvalue));
|
||||||
|
my $deltat= $hash->{".updateTime"} - $oldt if(defined($oldt));
|
||||||
|
if(defined($deltav) && defined($deltat) && ($deltat>= 1.0)) {
|
||||||
|
$result= $deltav/$deltat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readingsBulkUpdate($hash,$userReading,$result,1) if(defined($result));
|
||||||
|
# store value
|
||||||
|
$hash->{fhem}{'.userReadings'}{$userReading}{TIME}= $hash->{".updateTimestamp"};
|
||||||
|
$hash->{fhem}{'.userReadings'}{$userReading}{t}= $hash->{".updateTime"};
|
||||||
|
$hash->{fhem}{'.userReadings'}{$userReading}{value}= $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
evalStateFormat($hash);
|
evalStateFormat($hash);
|
||||||
|
|
||||||
# turn off updating mode
|
# turn off updating mode
|
||||||
delete $hash->{".updateTimestamp"};
|
delete $hash->{".updateTimestamp"};
|
||||||
|
delete $hash->{".updateTime"};
|
||||||
delete $hash->{".attreour"};
|
delete $hash->{".attreour"};
|
||||||
delete $hash->{".attreocr"};
|
delete $hash->{".attreocr"};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user