From 57eb68292f3a1eee1800c2251531b32704639ca3 Mon Sep 17 00:00:00 2001
From: rudolfkoenig <>
Date: Wed, 5 Apr 2017 11:36:44 +0000
Subject: [PATCH] fhem.pl: extern SetMagic, add AttrNum and InternalNum (Forum
#38276)
git-svn-id: https://svn.fhem.de/fhem/trunk@13904 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/docs/commandref_frame.html | 40 +++++++++++++++++++++----
fhem/docs/commandref_frame_DE.html | 48 ++++++++++++++++++++++++------
fhem/fhem.pl | 47 +++++++++++++++++++++++++----
3 files changed, 115 insertions(+), 20 deletions(-)
diff --git a/fhem/docs/commandref_frame.html b/fhem/docs/commandref_frame.html
index 59b1b2488..e53cff81b 100644
--- a/fhem/docs/commandref_frame.html
+++ b/fhem/docs/commandref_frame.html
@@ -1084,10 +1084,26 @@ The following local attributes are used by a wider range of devices:
From featurelevel 5.7 on the set and setreading command replaces:
- [device:name] with the reading, internal or attribute of the device, if
- both device and the reading, internal or attribute exists. You can use the
- r:, i: or a: prefix to restrict the search to one type, analogue to the
- devspec filtering.
+ both device and the reading, internal or attribute exists.
+
+ - You can use the r:, i: or a: prefix to restrict the search to one
+ type, analogue to the devspec filtering.
+ - The suffix :d retrieves the first number and converts it to an
+ integer.
+ - The suffix :r<n> retrieves the first number and rounds it to
+ <n> decimal places. If <n> is missing, then rounds it to
+ one decimal place.
+ - The suffix :t returns the timestamp (works only for readings)
+ - The suffix :sec returns the number of seconds since the reading was
+ set.
+
+ Example:
+
+ set Lamp blink [blinkDummy:number] [r:blinkDummy:duration:d]
+
+
- [device:name:d] same as above, but only the number is retrieved
+ - [device:name:sec] same as above, but only the number is retrieved
- {(perlExpression)} with the result of perlExpression.
The $DEV variable is additionally available, designating the set device
name.
@@ -1648,8 +1664,10 @@ The following local attributes are used by a wider range of devices:
Return the reading (the value in the Readings section of "list device")
-
- ReadingsNum(<devicename>,<reading>,<defaultvalue>)
- Return the reading as a number, i.e. delete non-numerical values.
+ ReadingsNum(<devicename>,<reading>,
+ <defaultvalue>,<round>)
+ Return the first number from a reading value.
+ Round id to <round> devimal places (optional parameter).
- ReadingsTimestamp(<devicename>,<reading>,<
defaultvalue>)
@@ -1670,12 +1688,24 @@ The following local attributes are used by a wider range of devices:
{ ReadingsTimestamp("wz", "measured-temp", 0)}
{ AttrVal("wz", "room", "none") }
+ -
+ AttrNum(<devicename>,<attribute>,
+ <defaultvalue>,<round>)
+ Return the first number from an attribute value.
+ Round id to <round> devimal places (optional parameter).
+
-
InternalVal(<devicename>,<property>,<defaultvalue>)
Return the internal value (the value in the Internals section of "list
device").
+ -
+ InternalNum(<devicename>,<property>,
+ <defaultvalue>,<round>)
+ Return the first number from an internal value.
+ Round id to <round> devimal places (optional parameter).
+
diff --git a/fhem/docs/commandref_frame_DE.html b/fhem/docs/commandref_frame_DE.html
index 6f953a576..e6f4e35c6 100644
--- a/fhem/docs/commandref_frame_DE.html
+++ b/fhem/docs/commandref_frame_DE.html
@@ -1153,10 +1153,23 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
- [device:name] mit dem Wert des Readings, Internals oder Attributes
für device, falls sowohl device, als auch Reading, Internal oder
- Attribut existiert, und nicht leer ist. Man kann einen der Prefixe r:, i:
- oder a: verwenden, um die Suche einzuschraenken, genau wie im devspec.
- - [device:name:d] wie ohne :d, aber alles nicht-numerische wird
- entfernt.
+ Attribut existiert, und nicht leer ist.
+
+ - Man kann einen der Präfixe r:, i: oder a: verwenden, um die
+ Suche einzuschränken, genau wie im devspec.
+ - Das Suffix :d extrahiert die erste Zahl als Ganzzahl.
+ - Das Suffix :r<n> extrahiert die erste Zahl, und rundet sie auf
+ <n> Dezimalstellen. Falls <n> fehlt, dann wird auf eine
+ Dezimalstelle gerundet.
+ - Das Suffix :t liefert den Zeitstempel des Readings
+ - Das Suffix :sec liefert Anzahl der Sekunden seit Änderung
+ des Readings.
+
+ Beispiel:
+
+ set Lamp blink [blinkDummy:number] [r:blinkDummy:duration:d]
+
+
- {(perlExpression)} mit dem Ergebnis der perlExpression.
$DEV wird dabei mit dem Namen des vom set betroffenen Gerätes ersetzt.
@@ -1784,9 +1797,11 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
dem "Readings"-Abschnitt von "list device" angezeigt wird)
-
- ReadingsNum(<devicename>,<reading>,<defaultvalue>)
- Wie ReadingsVal, löscht aber alles, was kein Zahl ist, um den Wert
- bei Berechnungen verwenden zu können.
+ ReadingsNum(<devicename>,<reading>,
+ <defaultvalue>,<round>)
+ Gibt die erste Zahl aus dem Readingswert zurück.
+ Falls <round> spezifiziert ist, wird sie auf diese Anzahl von
+ Dezimalstellen gerundet.
- ReadingsTimestamp(<devicename>,
<reading>,<defaultvalue>)
@@ -1798,7 +1813,7 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
-
AttrVal(<devicename>,<attribute>,<defaultvalue>)
- Gibt die gesetzteb Attribute des Gerätes zurück
+ Gibt das entsprechende Attribut des Gerätes zurück
{ Value("wz") }
{ OldValue("wz") }
@@ -1808,10 +1823,25 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
{ AttrVal("wz", "room", "none") }
-
- InternalVal(<devicename>,<reading>,<defaultvalue>)
+ AttrNum(<devicename>,<attribute>,
+ <defaultvalue>,<round>)
+ Gibt die erste Zahl aus dem Attributwert zurück.
+ Falls <round> spezifiziert ist, wird sie auf diese Anzahl von
+ Dezimalstellen gerundet.
+
+ -
+ InternalVal(<devicename>,<internal>,
+ <defaultvalue>)
Gibt den Inhalt der "internal" zurück (den Inhalt der in
dem "Internals"-Abschnitt von "list device" angezeigt wird)
+ -
+ InternalNum(<devicename>,<internal>,
+ <defaultvalue>,<round>)
+ Gibt die erste Zahl aus dem "internal" zurück.
+ Falls <round> spezifiziert ist, wird sie auf diese Anzahl von
+ Dezimalstellen gerundet.
+
diff --git a/fhem/fhem.pl b/fhem/fhem.pl
index b176589b3..10f6a1143 100755
--- a/fhem/fhem.pl
+++ b/fhem/fhem.pl
@@ -48,6 +48,7 @@ sub AnalyzeInput($);
sub AnalyzePerlCommand($$;$);
sub AssignIoPort($;$);
sub AttrVal($$$);
+sub AttrNum($$$;$);
sub CallFn(@);
sub CallInstanceFn(@);
sub CheckDuplicate($$@);
@@ -70,6 +71,7 @@ sub HandleTimeout();
sub IOWrite($@);
sub InternalTimer($$$;$);
sub InternalVal($$$);
+sub InternalNum($$$;$);
sub IsDevice($;$);
sub IsDisabled($);
sub IsDummy($);
@@ -82,7 +84,7 @@ sub OldTimestamp($);
sub OldValue($);
sub OpenLogfile($);
sub PrintHash($$);
-sub ReadingsNum($$$);
+sub ReadingsNum($$$;$);
sub ReadingsTimestamp($$$);
sub ReadingsVal($$$);
sub RefreshAuthList();
@@ -1660,16 +1662,28 @@ ReplaceSetMagic($$@) # Forum #38276
return $all if(!$hash);
if(!$t || $t eq "r:") {
my $r = $hash->{READINGS};
+ if($s && ($s eq ":t" || $s eq ":sec")) {
+ return $all if (!$r || !$r->{$n});
+ $val = $r->{$n}{TIME};
+ $val = time() - time_str2num($val) if($s eq ":sec");
+ return $val;
+ }
$val = $r->{$n}{VAL} if($r && $r->{$n});
}
$val = $hash->{$n} if(!defined($val) && (!$t || $t eq "i:"));
$val = $attr{$d}{$n} if(!defined($val) && (!$t || $t eq "a:") && $attr{$d});
return $all if(!defined($val));
- $val =~ s/[^-\.\d]//g if($s);
+
+ if($s && $val =~ /(-?\d+(\.\d+)?)/) {
+ $val = $1;
+ $s = ":r0" if($s eq ":d");
+ $val = round($val, defined($1) ? $1 : 1) if($s =~ /^:r(\d)?/);
+ }
return $val;
}
- $a=~s/(\[(.:)?([a-z0-9._]+):([a-z0-9._-]+)(:d)?\])/rsmVal($1,$2,$3,$4,$5)/egi;
+ $a =~ s/(\[([ari]:)?([a-z0-9._]+):([a-z0-9._-]+)(:(t|sec|d|r|r\d))?\])/
+ rsmVal($1,$2,$3,$4,$5)/egi;
$evalSpecials->{'%DEV'} = $hash->{NAME};
$a =~ s/{\((.*?)\)}/AnalyzePerlCommand($hash->{CL},$1,1)/egs;
@@ -3938,6 +3952,16 @@ InternalVal($$$)
return $default;
}
+sub
+InternalNum($$$;$)
+{
+ my ($d,$n,$default,$round) = @_;
+ my $val = InternalVal($d,$n,$default);
+ $val = ($val =~ /(-?\d+(\.\d+)?)/ ? $1 : "");
+ $val = round($val,$round) if($round);
+ return $val;
+}
+
sub
ReadingsVal($$$)
{
@@ -3952,11 +3976,12 @@ ReadingsVal($$$)
}
sub
-ReadingsNum($$$)
+ReadingsNum($$$;$)
{
- my ($d,$n,$default) = @_;
+ my ($d,$n,$default,$round) = @_;
my $val = ReadingsVal($d,$n,$default);
- $val =~ s/[^-\.\d]//g;
+ $val = ($val =~ /(-?\d+(\.\d+)?)/ ? $1 : "");
+ $val = round($val,$round) if($round);
return $val;
}
@@ -4017,6 +4042,16 @@ AttrVal($$$)
return $default;
}
+sub
+AttrNum($$$;$)
+{
+ my ($d,$n,$default,$round) = @_;
+ my $val = AttrVal($d,$n,$default);
+ $val = ($val =~ /(-?\d+(\.\d+)?)/ ? $1 : "");
+ $val = round($val,$round) if($round);
+ return $val;
+}
+
################################################################
# Functions used by modules.
sub