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:
parent
694902c61a
commit
7a5dbd4a8d
@ -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><configfilename></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::<dbtype></code> need to be installed (use
|
||||
<code>cpan -i <module></code> if your distribution does not have it).
|
||||
The modules <code>DBI</code> and <code>DBD::<dbtype></code>
|
||||
need to be installed (use <code>cpan -i <module></code>
|
||||
if your distribution does not have it).
|
||||
<br><br>
|
||||
|
||||
<code><regexp></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><DBType>_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><column_spec><br>
|
||||
For each column_spec return a set of data separated by
|
||||
a comment line on the current connection.<br>
|
||||
Syntax: <device>:<reading>:<default>:<fn><br>
|
||||
Syntax: <device>:<reading>:<default>:<fn>:<regexp><br>
|
||||
<ul>
|
||||
<li><device><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><regexp><br>
|
||||
The string is evaluated as a perl expression. $val is the
|
||||
current value returned from the Database. The regexp is executed
|
||||
before <fn> 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 <name> DbLog <configfilename> <regexp></code>
|
||||
<br><br>
|
||||
|
||||
Speichert Events in eine Datenbank. Die Datenbankverbindungsparameter werden
|
||||
definiert in <code><configfilename></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::<dbtype></code>
|
||||
müssen installiert werden (use <code>cpan -i <module></code>
|
||||
falls die eigene Distribution diese nicht schon mitbringt).
|
||||
<br><br>
|
||||
|
||||
<code><regexp></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/<DBType>_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 <name> <infile> <outfile> <from>
|
||||
<to> <column_spec> </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><in><br>
|
||||
Ein Dummy Parameter um eine Kompatibilität zum Filelog herzustellen.
|
||||
Dieser Parameter ist immer auf <code>-</code> zu setzen.
|
||||
</li>
|
||||
<li><out><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><from> / <to><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><column_spec><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: <device>:<reading>:<default>:<fn>:<regexp><br>
|
||||
<ul>
|
||||
<li><device><br>
|
||||
Der Name des Devices. Achtung: Groß/Kleinschreibung beachten!</li>
|
||||
<li><reading><br>
|
||||
Das REading des angegebenen Devices zur Datenselektion.
|
||||
Achtung: Groß/Kleinschreibung beachten!
|
||||
</li>
|
||||
<li><default><br>
|
||||
Zur Zeit noch nicht implementiert.
|
||||
</li>
|
||||
<li><fn>
|
||||
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<digit><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°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><regexp><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 <fn> Parameter ausgeführt.
|
||||
<br>
|
||||
Bitte zur Beachtung: Diese Zeichenkette darf keine Leerzeichen
|
||||
enthalten da diese sonst als <column_spec> Trennung
|
||||
interpretiert werden und alles nach dem Leerzeichen als neue
|
||||
<column_spec> 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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user