diff --git a/fhem/docs/commandref_frame.html b/fhem/docs/commandref_frame.html
index 17924a036..45abb07b4 100644
--- a/fhem/docs/commandref_frame.html
+++ b/fhem/docs/commandref_frame.html
@@ -370,13 +370,27 @@ A line ending with \ will be concatenated with the next one, so long lines
If a reading is listed in event-on-update-reading, an update of the
reading creates an event no matter whether the reading is also listed
in event-on-change-reading.
-
+
-
+
+ userReadings
+ A comma-separated list of user-defined readings. Each definition has the form
+ <reading> { <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 myPowerMeter userReadings power { ReadingsVal("myPowerMeter","count.A",0)/1250.0;; }
+ attr myMultiMeter userReadings power1 { ReadingsVal("myMultiMeter","count.A",0)/1250.0;; },
+ power2 { ReadingsVal("myMultiMeter","count.B",0)/1250.0;; }
+
+
+
Device specific attributes are documented in the corresponding device section.
-
+
Examples:
diff --git a/fhem/docs/commandref_frame_DE.html b/fhem/docs/commandref_frame_DE.html
index 8ffa01101..756e68a0e 100644
--- a/fhem/docs/commandref_frame_DE.html
+++ b/fhem/docs/commandref_frame_DE.html
@@ -380,7 +380,21 @@ Zeilen erstreckende Befehle, indem man keine \ am Zeilenende eingeben muss.
- Wenn ein "reading" in event-on-update-reading aufgeführt ist,
erzeugt eine Aktualisierung ein Ereignis unabhängig ob das
"reading" auch in event-on-change-reading aufgelistet ist.
-
+
+
+
+ userReadings
+ A comma-separated list of user-defined readings. Each definition has the form
+ <reading> { <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 myPowerMeter userReadings power { ReadingsVal("myPowerMeter","count.A",0)/1250.0;; }
+ attr myMultiMeter userReadings power1 { ReadingsVal("myMultiMeter","count.A",0)/1250.0;; },
+ power2 { ReadingsVal("myMultiMeter","count.B",0)/1250.0;; }
+
diff --git a/fhem/fhem.pl b/fhem/fhem.pl
index 565aa1242..e49b90c85 100755
--- a/fhem/fhem.pl
+++ b/fhem/fhem.pl
@@ -166,7 +166,7 @@ use vars qw(%addNotifyCB); # Used by event enhancers (e.g. avarage)
use vars qw($reread_active);
-my $AttrList = "room group comment alias eventMap";
+my $AttrList = "room group comment alias eventMap userReadings";
my %comments; # Comments from the include files
my $ipv6; # Using IPV6
@@ -318,6 +318,17 @@ if(int(@ARGV) == 2) {
# End of client code
###################################################
+
+###################################################
+# for debugging
+sub
+Debug($) {
+ my $msg= shift;
+ Log 1, "DEBUG>" . $msg;
+}
+###################################################
+
+
###################################################
# Server initialization
doGlobalDef($ARGV[0]);
@@ -1385,6 +1396,12 @@ CommandDeleteAttr($$)
}
$a[0] = $sdev;
+
+ if($a[1] eq "userReadings") {
+ Debug "Deleting userReadings for $sdev";
+ delete($defs{$sdev}{fhem}{userReadings});
+ }
+
$ret = CallFn($sdev, "AttrFn", "del", @a);
if($ret) {
push @rets, $ret;
@@ -1747,6 +1764,27 @@ CommandAttr($$)
}
}
+ if($a[1] eq "userReadings") {
+
+ my %userReadings;
+
+ my $arg= $a[2]; # myReading1 { codecodecode1 }, myReading2 { codecodecode2 }, myReading3 { codecodecode3 }
+
+ my $regexi= '\s*(\w+)\s+({.*?})\s*'; # matches myReading1 { codecodecode1 }
+ my $regexo= '^(' . $regexi . ')(,\s*(.*))*$';
+
+ Debug "arg is $arg";
+
+ while($arg =~ /$regexo/) {
+ my $userReading= $2;
+ my $perlCode= $3;
+ #Debug sprintf("userReading %s has perlCode %s", $userReading, $perlCode);
+ $userReadings{$userReading}= $perlCode;
+ $arg= defined($5) ? $5 : "";
+ }
+ $defs{$sdev}{fhem}{userReadings}= \%userReadings;
+ }
+
if($a[1] eq "IODev" && (!$a[2] || !defined($defs{$a[2]}))) {
push @rets,"$sdev: unknown IODev specified";
next;
@@ -1770,6 +1808,7 @@ CommandAttr($$)
$defs{$sdev}{NR} = $devcount++
if($defs{$ioname}{NR} > $defs{$sdev}{NR});
}
+
}
Log 3, join(" ", @rets) if(!$cl && @rets);
return join("\n", @rets);
@@ -2750,11 +2789,6 @@ addEvent($$)
#
################################################################
-sub
-Debug($) {
- my $msg= shift;
- Log 1, "DEBUG>" . $msg;
-}
# get the names of interfaces for the device represented by the $hash
# empty list is returned if interfaces are not defined
@@ -2927,6 +2961,7 @@ readingsBeginUpdate($)
return $now;
}
+
#
# Call readingsEndUpdate when you are done updating readings.
# This optionally calls DoTrigger to propagate the changes.
@@ -2937,6 +2972,20 @@ readingsEndUpdate($$)
my ($hash,$dotrigger)= @_;
my $name = $hash->{NAME};
+ # process user readings
+ if(defined($hash->{fhem}{userReadings})) {
+ my %userReadings= %{$hash->{fhem}{userReadings}};
+ foreach my $userReading (keys %userReadings) {
+ Debug "Evaluating " . $userReadings{$userReading};
+ my $value= eval $userReadings{$userReading};
+ if($@) {
+ $value = "Error evaluating $name userReading $userReading: $@";
+ Log 1, $value;
+ }
+ readingsBulkUpdate($hash,$userReading,$value,1);
+ }
+ }
+
# turn off updating mode
delete $hash->{".updateTimestamp"};
delete $hash->{".attreour"};
@@ -2966,7 +3015,6 @@ readingsEndUpdate($$)
}
$hash->{STATE} = ReplaceEventMap($name, $st, 1) if(defined($st));
-
# propagate changes
if($dotrigger && $init_done) {
DoTrigger($name, undef, 1) if(!$readingsUpdateDelayTrigger);