2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-20 19:36:02 +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
# written by Dr. Boris Neubert 2007-12-30
@ -121,14 +122,12 @@ DbLog_ParseEvent($$)
}
# Onewire
elsif(($type eq "OWAD") ||
($type eq "OWSWITCH") ||
($type eq "OWMULTI")) {
$reading = "data";
$value = $event;
}
# FS20
elsif(($type eq "FS20") ||
($type eq "X10")) {
@ -214,7 +213,6 @@ DbLog_ParseEvent($$)
if($event =~ m(T:.*)) { $reading= "data"; $value= $event; }
if($reading eq "temperature") { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
if($reading eq "temperature") { $value=~ s/([-\.\d]+).*/$1/; $unit= "°C"; } #OWTHERM
if($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; }
if($reading eq "battery") {
$value=~ s/ok/1/;
@ -223,7 +221,6 @@ DbLog_ParseEvent($$)
}
}
# BS
elsif($type eq "BS") {
if($event =~ m(brightness:.*)) {
@ -475,11 +472,12 @@ DbLog_Get($@)
#extract the Device:Reading arguments into @readings array
for(my $i = 0; $i < int(@a); $i++) {
@fld = split(":", $a[$i], 4);
$readings[$i][0] = $fld[0];
$readings[$i][1] = $fld[1];
$readings[$i][2] = $fld[2];
$readings[$i][3] = $fld[3];
@fld = split(":", $a[$i], 5);
$readings[$i][0] = $fld[0]; # Device
$readings[$i][1] = $fld[1]; # Reading
$readings[$i][2] = $fld[2]; # Default
$readings[$i][3] = $fld[3]; # function
$readings[$i][4] = $fld[4]; # regexp
}
my $dbh= $hash->{DBH};
@ -531,7 +529,7 @@ DbLog_Get($@)
".$sqlspec{all}."
FROM history
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{to_timestamp}
ORDER BY TIMESTAMP";
@ -551,20 +549,32 @@ DbLog_Get($@)
$writeout = 0;
$out_value = "";
$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 ###################
if(@readings[$i]->[3] eq "int") {
#nur den integerwert uebernehmen falls zb value=15°C
if($readings[$i]->[3] eq "int") {
#nur den integerwert uebernehmen falls zb value=15?C
$out_value = $1 if($sql_value =~ m/^(\d+).*/o);
$out_tstamp = $sql_timestamp;
$writeout=1;
} elsif (@readings[$i]->[3] =~ m/^int(\d+).*/o) {
#übernehme den Dezimalwert mit den angegebenen Stellen an Nachkommastellen
} elsif ($readings[$i]->[3] =~ m/^int(\d+).*/o) {
#?bernehme den Dezimalwert mit den angegebenen Stellen an Nachkommastellen
$out_value = $1 if($sql_value =~ m/^([-\.\d]+).*/o);
$out_tstamp = $sql_timestamp;
$writeout=1;
} elsif (@readings[$i]->[3] eq "delta-h") {
} elsif ($readings[$i]->[3] eq "delta-h") {
#Berechnung eines Stundenwertes
%tstamp = DbLog_explode_datetime($sql_timestamp, undef);
if($lastd[$i] eq "undef") {
@ -580,7 +590,7 @@ DbLog_Get($@)
$maxval = -999999;
$writeout=1;
}
} elsif (@readings[$i]->[3] eq "delta-d") {
} elsif ($readings[$i]->[3] eq "delta-d") {
#Berechnung eines Tageswertes
%tstamp = DbLog_explode_datetime($sql_timestamp, undef);
if($lastd[$i] eq "undef") {
@ -596,15 +606,6 @@ DbLog_Get($@)
$maxval = -999999;
$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 {
$out_value = $sql_value;
$out_tstamp = $sql_timestamp;
@ -642,10 +643,10 @@ DbLog_Get($@)
} #while fetchrow
######## 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_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}, $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");
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);
} else {
@ -654,7 +655,7 @@ DbLog_Get($@)
}
}
# 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
#Ueberfuehren der gesammelten Werte in die globale Variable %data
@ -688,7 +689,6 @@ DbLog_Get($@)
1;
=pod
=begin html
<a name="DbLog"></a>
@ -704,20 +704,20 @@ DbLog_Get($@)
Log events to a database. The database connection is defined in
<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
visible in the output of the <a href="../docs/commandref.html#list">list</a> command.
<br><br>
You must have <code>93_DbLog.pm</code> in the <code>FHEM</code> subdirectory
to make this work. Additionally, the modules <code>DBI</code> and
<code>DBD::&lt;dbtype&gt;</code> need to be installed (use
<code>cpan -i &lt;module&gt;</code> if your distribution does not have it).
The modules <code>DBI</code> and <code>DBD::&lt;dbtype&gt;</code>
need to be installed (use <code>cpan -i &lt;module&gt;</code>
if your distribution does not have it).
<br><br>
<code>&lt;regexp&gt;</code> is the same as in <a href="../docs/commandref.html#FileLog">FileLog</a>.
<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
<code>history</code>. The latter contains all events whereas the former only
contains the last event for any given reading and device.
@ -779,7 +779,7 @@ DbLog_Get($@)
<li>&lt;column_spec&gt;<br>
For each column_spec return a set of data separated by
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>
<li>&lt;device&gt;<br>
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.
Used if the column contains a counter, as is the case for the
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>
<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>
<br><br>
Examples:
<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>
like from 10am until 20pm at 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>
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 - - 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>
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>
and output for port B is like this: <code>2012-11-20_10:23:54 66.647</code></li>
</ul>
@ -833,6 +836,165 @@ DbLog_Get($@)
=end html
=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
=cut