2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-21 01:46:08 +00:00

- deutsche Doku ergänzt

- 5.Parameter in GET-Funktion in der column_spec hinzugefügt
  hiermit können komplexe Regexp zur Modifizierung des gelesenen Readings übergeben werden


git-svn-id: https://svn.fhem.de/fhem/trunk@2267 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
tobiasfaust 2012-12-05 06:57:04 +00:00
parent 694902c61a
commit 7a5dbd4a8d

View File

@ -1,5 +1,6 @@
############################################## ##############################################
# $Id$
# #
# 93_DbLog.pm # 93_DbLog.pm
# written by Dr. Boris Neubert 2007-12-30 # written by Dr. Boris Neubert 2007-12-30
@ -121,14 +122,12 @@ DbLog_ParseEvent($$)
} }
# Onewire # Onewire
elsif(($type eq "OWAD") || elsif(($type eq "OWAD") ||
($type eq "OWSWITCH") || ($type eq "OWSWITCH") ||
($type eq "OWMULTI")) { ($type eq "OWMULTI")) {
$reading = "data"; $reading = "data";
$value = $event; $value = $event;
} }
# FS20 # FS20
elsif(($type eq "FS20") || elsif(($type eq "FS20") ||
($type eq "X10")) { ($type eq "X10")) {
@ -214,7 +213,6 @@ DbLog_ParseEvent($$)
if($event =~ m(T:.*)) { $reading= "data"; $value= $event; } if($event =~ m(T:.*)) { $reading= "data"; $value= $event; }
if($reading eq "temperature") { $value=~ s/ \(Celsius\)//; $unit= "°C"; } if($reading eq "temperature") { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
if($reading eq "temperature") { $value=~ s/([-\.\d]+).*/$1/; $unit= "°C"; } #OWTHERM if($reading eq "temperature") { $value=~ s/([-\.\d]+).*/$1/; $unit= "°C"; } #OWTHERM
if($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; } if($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; }
if($reading eq "battery") { if($reading eq "battery") {
$value=~ s/ok/1/; $value=~ s/ok/1/;
@ -223,7 +221,6 @@ DbLog_ParseEvent($$)
} }
} }
# BS # BS
elsif($type eq "BS") { elsif($type eq "BS") {
if($event =~ m(brightness:.*)) { if($event =~ m(brightness:.*)) {
@ -475,11 +472,12 @@ DbLog_Get($@)
#extract the Device:Reading arguments into @readings array #extract the Device:Reading arguments into @readings array
for(my $i = 0; $i < int(@a); $i++) { for(my $i = 0; $i < int(@a); $i++) {
@fld = split(":", $a[$i], 4); @fld = split(":", $a[$i], 5);
$readings[$i][0] = $fld[0]; $readings[$i][0] = $fld[0]; # Device
$readings[$i][1] = $fld[1]; $readings[$i][1] = $fld[1]; # Reading
$readings[$i][2] = $fld[2]; $readings[$i][2] = $fld[2]; # Default
$readings[$i][3] = $fld[3]; $readings[$i][3] = $fld[3]; # function
$readings[$i][4] = $fld[4]; # regexp
} }
my $dbh= $hash->{DBH}; my $dbh= $hash->{DBH};
@ -531,7 +529,7 @@ DbLog_Get($@)
".$sqlspec{all}." ".$sqlspec{all}."
FROM history FROM history
WHERE 1=1 WHERE 1=1
AND (DEVICE || '|' || READING) = ('".@readings[$i]->[0]."|".@readings[$i]->[1]."') AND (DEVICE || '|' || READING) = ('".$readings[$i]->[0]."|".$readings[$i]->[1]."')
AND TIMESTAMP > $sqlspec{from_timestamp} AND TIMESTAMP > $sqlspec{from_timestamp}
AND TIMESTAMP < $sqlspec{to_timestamp} AND TIMESTAMP < $sqlspec{to_timestamp}
ORDER BY TIMESTAMP"; ORDER BY TIMESTAMP";
@ -551,20 +549,32 @@ DbLog_Get($@)
$writeout = 0; $writeout = 0;
$out_value = ""; $out_value = "";
$out_tstamp = ""; $out_tstamp = "";
############ Auswerten des 5. Parameters: Regexp ###################
if($readings[$i]->[4]) {
#evaluate
my $val = $sql_value;
eval("$readings[$i]->[4]");
$sql_value = $val;
if($@) {Log 3, "DbLog: Fehler in der übergebenen Funktion: <".$readings[$i]->[4].">, Fehler: $@";}
$out_tstamp = $sql_timestamp;
$writeout=1;
}
############ Auswerten des 4. Parameters: function ################### ############ Auswerten des 4. Parameters: function ###################
if(@readings[$i]->[3] eq "int") { if($readings[$i]->[3] eq "int") {
#nur den integerwert uebernehmen falls zb value=15°C #nur den integerwert uebernehmen falls zb value=15?C
$out_value = $1 if($sql_value =~ m/^(\d+).*/o); $out_value = $1 if($sql_value =~ m/^(\d+).*/o);
$out_tstamp = $sql_timestamp; $out_tstamp = $sql_timestamp;
$writeout=1; $writeout=1;
} elsif (@readings[$i]->[3] =~ m/^int(\d+).*/o) { } elsif ($readings[$i]->[3] =~ m/^int(\d+).*/o) {
#übernehme den Dezimalwert mit den angegebenen Stellen an Nachkommastellen #?bernehme den Dezimalwert mit den angegebenen Stellen an Nachkommastellen
$out_value = $1 if($sql_value =~ m/^([-\.\d]+).*/o); $out_value = $1 if($sql_value =~ m/^([-\.\d]+).*/o);
$out_tstamp = $sql_timestamp; $out_tstamp = $sql_timestamp;
$writeout=1; $writeout=1;
} elsif (@readings[$i]->[3] eq "delta-h") { } elsif ($readings[$i]->[3] eq "delta-h") {
#Berechnung eines Stundenwertes #Berechnung eines Stundenwertes
%tstamp = DbLog_explode_datetime($sql_timestamp, undef); %tstamp = DbLog_explode_datetime($sql_timestamp, undef);
if($lastd[$i] eq "undef") { if($lastd[$i] eq "undef") {
@ -580,7 +590,7 @@ DbLog_Get($@)
$maxval = -999999; $maxval = -999999;
$writeout=1; $writeout=1;
} }
} elsif (@readings[$i]->[3] eq "delta-d") { } elsif ($readings[$i]->[3] eq "delta-d") {
#Berechnung eines Tageswertes #Berechnung eines Tageswertes
%tstamp = DbLog_explode_datetime($sql_timestamp, undef); %tstamp = DbLog_explode_datetime($sql_timestamp, undef);
if($lastd[$i] eq "undef") { if($lastd[$i] eq "undef") {
@ -596,15 +606,6 @@ DbLog_Get($@)
$maxval = -999999; $maxval = -999999;
$writeout=1; $writeout=1;
} }
} elsif(@readings[$i]->[3]) {
#evaluate
my $val = $sql_value;
eval("@readings[$i]->[3]");
$out_value = $val;
if($@) {Log 3, "DbLog: Fehler in der übergebenen Funktion: <".@readings[$i]->[3].">, Fehler: $@";}
$out_tstamp = $sql_timestamp;
$writeout=1;
} else { } else {
$out_value = $sql_value; $out_value = $sql_value;
$out_tstamp = $sql_timestamp; $out_tstamp = $sql_timestamp;
@ -642,10 +643,10 @@ DbLog_Get($@)
} #while fetchrow } #while fetchrow
######## den letzten Abschlusssatz rausschreiben ########## ######## den letzten Abschlusssatz rausschreiben ##########
if(@readings[$i]->[3] eq "delta-h" || @readings[$i]->[3] eq "delta-d") { if($readings[$i]->[3] eq "delta-h" || $readings[$i]->[3] eq "delta-d") {
$out_value = sprintf("%0.1f", $maxval - $minval); $out_value = sprintf("%0.1f", $maxval - $minval);
$out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, $lasttstamp{hour}, "30", "00") if(@readings[$i]->[3] eq "delta-h"); $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, $lasttstamp{hour}, "30", "00") if($readings[$i]->[3] eq "delta-h");
$out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, "00", "00", "00") if(@readings[$i]->[3] eq "delta-d"); $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, "00", "00", "00") if($readings[$i]->[3] eq "delta-d");
if(uc($outf) eq "ALL") { if(uc($outf) eq "ALL") {
$retval .= sprintf("%s: %s %s %s %s %s %s\n", $out_tstamp, $sql_dev, $type, $event, $sql_reading, $out_value, $unit); $retval .= sprintf("%s: %s %s %s %s %s %s\n", $out_tstamp, $sql_dev, $type, $event, $sql_reading, $out_value, $unit);
} else { } else {
@ -654,7 +655,7 @@ DbLog_Get($@)
} }
} }
# DatenTrenner setzen # DatenTrenner setzen
$retval .= "#@readings[$i]->[0]:@readings[$i]->[1]:@readings[$i]->[2]:@readings[$i]->[3]\n"; $retval .= "#$readings[$i]->[0]:$readings[$i]->[1]:$readings[$i]->[2]:$readings[$i]->[3]\n";
} #for @readings } #for @readings
#Ueberfuehren der gesammelten Werte in die globale Variable %data #Ueberfuehren der gesammelten Werte in die globale Variable %data
@ -688,7 +689,6 @@ DbLog_Get($@)
1; 1;
=pod =pod
=begin html =begin html
<a name="DbLog"></a> <a name="DbLog"></a>
@ -704,20 +704,20 @@ DbLog_Get($@)
Log events to a database. The database connection is defined in Log events to a database. The database connection is defined in
<code>&lt;configfilename&gt;</code> (see sample configuration file <code>&lt;configfilename&gt;</code> (see sample configuration file
<code>db.conf</code>). The configuration is stored in a separate file <code>contrib/dblog/db.conf</code>). The configuration is stored in a separate file
to avoid storing the password in the main configuration file and to have it to avoid storing the password in the main configuration file and to have it
visible in the output of the <a href="../docs/commandref.html#list">list</a> command. visible in the output of the <a href="../docs/commandref.html#list">list</a> command.
<br><br> <br><br>
You must have <code>93_DbLog.pm</code> in the <code>FHEM</code> subdirectory The modules <code>DBI</code> and <code>DBD::&lt;dbtype&gt;</code>
to make this work. Additionally, the modules <code>DBI</code> and need to be installed (use <code>cpan -i &lt;module&gt;</code>
<code>DBD::&lt;dbtype&gt;</code> need to be installed (use if your distribution does not have it).
<code>cpan -i &lt;module&gt;</code> if your distribution does not have it).
<br><br> <br><br>
<code>&lt;regexp&gt;</code> is the same as in <a href="../docs/commandref.html#FileLog">FileLog</a>. <code>&lt;regexp&gt;</code> is the same as in <a href="../docs/commandref.html#FileLog">FileLog</a>.
<br><br> <br><br>
Sample code to create a MySQL database is in <code>fhemdb_create.sql</code>. Sample code to create a MySQL/PostgreSQL database is in
<code>&lt;DBType&gt;_create.sql</code>.
The database contains two tables: <code>current</code> and The database contains two tables: <code>current</code> and
<code>history</code>. The latter contains all events whereas the former only <code>history</code>. The latter contains all events whereas the former only
contains the last event for any given reading and device. contains the last event for any given reading and device.
@ -779,7 +779,7 @@ DbLog_Get($@)
<li>&lt;column_spec&gt;<br> <li>&lt;column_spec&gt;<br>
For each column_spec return a set of data separated by For each column_spec return a set of data separated by
a comment line on the current connection.<br> a comment line on the current connection.<br>
Syntax: &lt;device&gt;:&lt;reading&gt;:&lt;default&gt;:&lt;fn&gt;<br> Syntax: &lt;device&gt;:&lt;reading&gt;:&lt;default&gt;:&lt;fn&gt;:&lt;regexp&gt;<br>
<ul> <ul>
<li>&lt;device&gt;<br> <li>&lt;device&gt;<br>
The name of the device. Case sensitive</li> The name of the device. Case sensitive</li>
@ -803,25 +803,28 @@ DbLog_Get($@)
Return the delta of the values for a given hour or a given day. Return the delta of the values for a given hour or a given day.
Used if the column contains a counter, as is the case for the Used if the column contains a counter, as is the case for the
KS300 rain column.</li> KS300 rain column.</li>
<li>everything else<br>
The string is evaluated as a perl expression. $val is the
current value returned from the Database.<br>Note: The string/perl
expression cannot contain spaces, as the part after the space
will be considered as the next column_spec.</li>
</ul></li> </ul></li>
<li>&lt;regexp&gt;<br>
The string is evaluated as a perl expression. $val is the
current value returned from the Database. The regexp is executed
before &lt;fn&gt; parameter.<br>
Note: The string/perl expression cannot contain spaces,
as the part after the space will be considered as the
next column_spec.
</li>
</ul></li> </ul></li>
</ul> </ul>
<br><br> <br><br>
Examples: Examples:
<ul> <ul>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 KS300:temperature::</code></li> <li><code>get myDbLog - - 2012-11-10 2012-11-20 KS300:temperature</code></li>
<li><code>get myDbLog - - 2012-11-10_10 2012-11-10_20 KS300:temperature::int1</code><br> <li><code>get myDbLog - - 2012-11-10_10 2012-11-10_20 KS300:temperature::int1</code><br>
like from 10am until 20pm at 10.11.2012</li> like from 10am until 08pm at 10.11.2012</li>
<li><code>get myDbLog - all 2012-11-10 2012-11-20 KS300:temperature::</code></li> <li><code>get myDbLog - all 2012-11-10 2012-11-20 KS300:temperature</code></li>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 KS300:temperature:: KS300:rain::delta-h KS300:rain::delta-d</code></li> <li><code>get myDbLog - - 2012-11-10 2012-11-20 KS300:temperature KS300:rain::delta-h KS300:rain::delta-d</code></li>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 MyFS20:data::$val=~s/(on|off).*/$1eq"on"?1:0/eg</code><br> <li><code>get myDbLog - - 2012-11-10 2012-11-20 MyFS20:data:::$val=~s/(on|off).*/$1eq"on"?1:0/eg</code><br>
return 1 for all occurance of on* (on|on-for-timer etc) and 0 for all off*</li> return 1 for all occurance of on* (on|on-for-timer etc) and 0 for all off*</li>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 Bodenfeuchte:data::$val=~s/.*B:\s([-\.\d]+).*/$1/eg</code><br> <li><code>get myDbLog - - 2012-11-10 2012-11-20 Bodenfeuchte:data:::$val=~s/.*B:\s([-\.\d]+).*/$1/eg</code><br>
Example of OWAD: value like this: <code>"A: 49.527 % B: 66.647 % C: 9.797 % D: 0.097 V"</code><br> Example of OWAD: value like this: <code>"A: 49.527 % B: 66.647 % C: 9.797 % D: 0.097 V"</code><br>
and output for port B is like this: <code>2012-11-20_10:23:54 66.647</code></li> and output for port B is like this: <code>2012-11-20_10:23:54 66.647</code></li>
</ul> </ul>
@ -833,6 +836,165 @@ DbLog_Get($@)
=end html =end html
=begin html_DE =begin html_DE
<a name="DbLog"></a>
<h3>DbLog</h3>
<ul>
<br>
<a name="DbLogdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; DbLog &lt;configfilename&gt; &lt;regexp&gt;</code>
<br><br>
Speichert Events in eine Datenbank. Die Datenbankverbindungsparameter werden
definiert in <code>&lt;configfilename&gt;</code>. (Vergleiche
Beipspielkonfigurationsdatei in <code>contrib/dblog/db.conf</code>).<br>
Die Konfiguration ist in einer sparaten Datei abgelegt um das Datenbankpasswort
nicht in Klartext in der FHEM-Haupt-Konfigurationsdatei speichern zu müssen.
Ansonsten wäre es mittels des <a href="../docs/commandref.html#list">list</a>
Befehls einfach auslesbar.
<br><br>
Die Perl-Module <code>DBI</code> and <code>DBD::&lt;dbtype&gt;</code>
müssen installiert werden (use <code>cpan -i &lt;module&gt;</code>
falls die eigene Distribution diese nicht schon mitbringt).
<br><br>
<code>&lt;regexp&gt;</code> ist identisch wie <a href="../docs/commandref.html#FileLog">FileLog</a>.
<br><br>
Ein Beispielcode zum Erstellen einer MySQL/PostGreSQL Datenbak ist in
<code>contrib/dblog/&lt;DBType&gt;_create.sql</code> zu finden.
Die Datenbank beinhaltet 2 Tabellen: <code>current</code> und
<code>history</code>. Die Tabelle <code>current</code> enthält den letzten Stand
pro Device und Reading. In der Tabelle <code>history</code> sind alle
Events historisch gespeichert.
Die Tabellenspalten haben folgende Bedeutung:
<ol>
<li>TIMESTAMP: Zeitpunkt des Events, z.B. <code>2007-12-30 21:45:22</code></li>
<li>DEVICE: name des Devices, z.B. <code>Wetterstation</code></li>
<li>TYPE: Type des Devices, z.B. <code>KS300</code></li>
<li>EVENT: das auftretende Event als volle Zeichenkette
z.B. <code>humidity: 71 (%)</code></li>
<li>READING: Name des Readings, ermittelt aus dem Event,
z.B. <code>humidity</code></li>
<li>VALUE: aktueller Wert des Readings, ermittelt aus dem Event,
z.B. <code>71</code></li>
<li>UNIT: Einheit, ermittelt aus dem Event, z.B. <code>%</code></li>
</ol>
Der Wert des Rreadings ist optimiert für eine automatisierte Nachverarbeitung
z.B. <code>yes</code> ist transformiert nach <code>1</code>
<br><br>
Die gespeicherten Werte können mittels GET Funktion angezeigt werden:
<ul>
<code>get myDbLog - - 2012-11-10 2012-11-10 KS300:temperature</code>
</ul>
<br><br>
<b>Beispiel:</b>
<ul>
<code>Speichert alles in der Datenbank</code><br>
<code>define myDbLog DbLog /etc/fhem/db.conf .*:.*</code>
</ul>
</ul>
<a name="DbLogset"></a>
<b>Set</b> <ul>N/A</ul><br>
<a name="DbLogget"></a>
<b>Get</b>
<ul>
<code>get &lt;name&gt; &lt;infile&gt; &lt;outfile&gt; &lt;from&gt;
&lt;to&gt; &lt;column_spec&gt; </code>
<br><br>
Ließt Daten aus der Datenbank. Wird durch die Frontends benutzt um Plots
zu generieren ohne selbst auf die Datenank zugreifen zu müssen.
<br>
<ul>
<li>&lt;in&gt;<br>
Ein Dummy Parameter um eine Kompatibilität zum Filelog herzustellen.
Dieser Parameter ist immer auf <code>-</code> zu setzen.
</li>
<li>&lt;out&gt;<br>
Ein Dummy Parameter um eine Kompatibilität zum Filelog herzustellen.
Dieser Parameter ist immer auf <code>-</code> zu setzen um die
Ermittlung der Daten aus der Datenbank für die Plotgenerierung zu prüfen.<br>
Durchd ie Angabe des Schlüsselworts <code>all</code> werden alle
Spalten der Datenbank ausgegeben.
</li>
<li>&lt;from&gt; / &lt;to&gt;<br>
Wird benutzt um den Zeitraum der Daten einzugrenzen. Es ist das folgende
Zeitformat oder ein Teilstring davon zu benutzen:<br>
<ul><code>YYYY-MM-DD_HH24:MI:SS</code></ul></li>
<li>&lt;column_spec&gt;<br>
Für jede column_spec Gruppe wird ein Datenset zurückgegeben welches
durch einen Kommentar getrennt wird. Dieser Kommentar repräsentiert
die column_spec.<br>
Syntax: &lt;device&gt;:&lt;reading&gt;:&lt;default&gt;:&lt;fn&gt;:&lt;regexp&gt;<br>
<ul>
<li>&lt;device&gt;<br>
Der Name des Devices. Achtung: Groß/Kleinschreibung beachten!</li>
<li>&lt;reading&gt;<br>
Das REading des angegebenen Devices zur Datenselektion.
Achtung: Groß/Kleinschreibung beachten!
</li>
<li>&lt;default&gt;<br>
Zur Zeit noch nicht implementiert.
</li>
<li>&lt;fn&gt;
Angabe einer speziellen Funktion:
<ul>
<li>int<br>
Ermittelt den Zahlenwert ab dem Anfang der Zeichenkette aus der
Spalte "VALUE". Benutzt z.B. für Ausprägungen wie 10%.
</li>
<li>int&lt;digit&gt;<br>
Ermittelt den Zahlenwert ab dem Anfang der Zeichenkette aus der
Spalte "VALUE", inclusive negativen Vorzeichen und Dezimaltrenner.
Benutzt z.B. für Ausprägungen wie -5.7&deg;C.
</li>
<li>delta-h / delta-d<br>
Ermittelt die relative Veränderung eines Zahlenwertes pro Stunde
oder pro Tag. Wird benutzt z.B. für Spalten die einen
hochlaufenden Zähler enthalten wie im Falle für ein KS300 Regenzähler
oder dem 1-wire Modul OWCOUNT.
</li>
</ul></li>
<li>&lt;regexp&gt;<br>
Diese Zeichenkette wird als Perl Befehl ausgewertet. $val ist der
aktuelle Wert die die Datenbank für ein Device/Reading ausgibt.
Die regexp wird vor dem angegebenen &lt;fn&gt; Parameter ausgeführt.
<br>
Bitte zur Beachtung: Diese Zeichenkette darf keine Leerzeichen
enthalten da diese sonst als &lt;column_spec&gt; Trennung
interpretiert werden und alles nach dem Leerzeichen als neue
&lt;column_spec&gt; gesehen wird.
</li>
</ul></li>
</ul>
<br><br>
<b>Beispiele:</b>
<ul>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 KS300:temperature</code></li>
<li><code>get myDbLog - - 2012-11-10_10 2012-11-10_20 KS300:temperature::int1</code><br>
gibt Daten aus von 10Uhr bis 20Uhr am 10.11.2012</li>
<li><code>get myDbLog - all 2012-11-10 2012-11-20 KS300:temperature</code></li>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 KS300:temperature KS300:rain::delta-h KS300:rain::delta-d</code></li>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 MyFS20:data:::$val=~s/(on|off).*/$1eq"on"?1:0/eg</code><br>
gibt 1 zurück für alle Ausprägungen von on* (on|on-for-timer etc) und 0 für alle off*</li>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 Bodenfeuchte:data:::$val=~s/.*B:\s([-\.\d]+).*/$1/eg</code><br>
Beispiel von OWAD: Ein Wert wie z.B.: <code>"A: 49.527 % B: 66.647 % C: 9.797 % D: 0.097 V"</code><br>
und die Ausgabe ist für das Reading B folgende: <code>2012-11-20_10:23:54 66.647</code></li>
</ul>
<br><br>
</ul>
<a name="DbLogattr"></a>
<b>Attributes</b> <ul>N/A</ul><br>
</ul>
=end html_DE =end html_DE
=cut =cut