@@ -6,7 +6,7 @@
# written by Dr. Boris Neubert 2007-12-30
# e-mail: omega at online dot de
#
# modified by Tobias Faust 2012-06-26
# modified and maintained by Tobias Faust since 2012-06-26
# e-mail: tobias dot faust at online dot de
#
##############################################
@@ -17,11 +17,8 @@ use warnings;
use DBI ;
use Data::Dumper ;
sub DbLog ($$$) ;
################################################################
sub
DbLog_Initialize ($)
sub DbLog_Initialize ($)
{
my ( $ hash ) = @ _ ;
@@ -36,8 +33,7 @@ DbLog_Initialize($)
}
###############################################################
sub
DbLog_Define ($@)
sub DbLog_Define ($@)
{
my ( $ hash , $ def ) = @ _ ;
my @ a = split ( "[ \t][ \t]*" , $ def ) ;
@@ -64,8 +60,7 @@ DbLog_Define($@)
}
#####################################
sub
DbLog_Undef ($$)
sub DbLog_Undef ($$)
{
my ( $ hash , $ name ) = @ _ ;
my $ dbh = $ hash - > { DBH } ;
@@ -79,8 +74,7 @@ DbLog_Undef($$)
# DbLog-Instanz aufgerufen
#
################################################################
sub
DbLog_Attr (@)
sub DbLog_Attr (@)
{
my @ a = @ _ ;
my $ do = 0 ;
@@ -101,8 +95,7 @@ DbLog_Attr(@)
# Parsefunktion, abhaengig vom Devicetyp
#
################################################################
sub
DbLog_ParseEvent ($$$)
sub DbLog_ParseEvent ($$$)
{
my ( $ device , $ type , $ event ) = @ _ ;
my @ result ;
@@ -159,6 +152,14 @@ DbLog_ParseEvent($$$)
}
}
# FBDECT
elsif ( ( $ type eq "FBDECT" ) ) {
if ( $ value =~ /([\.\d]+)\s([a-z])/i ) {
$ value = $ 1 ;
$ unit = $ 2 ;
}
}
# MAX
elsif ( ( $ type eq "MAX" ) ) {
$ unit = "°C" if ( lc ( $ reading ) =~ m/temp/ ) ;
@@ -339,6 +340,60 @@ DbLog_ParseEvent($$$)
return @ result ;
}
################################################################
#
# param1: hash
# param2: DbLogType -> Current oder History oder Current/History
# param4: Timestamp
# param5: Device
# param6: Type
# param7: Event
# param8: Reading
# param9: Value
# param10: Unit
#
################################################################
sub DbLog_Push (@) {
my ( $ hash , $ DbLogType , $ timestamp , $ device , $ type , $ event , $ reading , $ value , $ unit ) = @ _ ;
my $ dbh = $ hash - > { DBH } ;
$ dbh - > { RaiseError } = 1 ;
$ dbh - > begin_work ( ) ;
my $ sth_ih = $ dbh - > prepare_cached ( "INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)" ) if ( lc ( $ DbLogType ) =~ m (history) ) ;
my $ sth_ic = $ dbh - > prepare_cached ( "INSERT INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)" ) if ( lc ( $ DbLogType ) =~ m (current) ) ;
my $ sth_uc = $ dbh - > prepare_cached ( "UPDATE current SET TIMESTAMP=?, TYPE=?, EVENT=?, VALUE=?, UNIT=? WHERE (DEVICE=?) AND (READING=?)" ) if ( lc ( $ DbLogType ) =~ m (current) ) ;
# insert into history
if ( lc ( $ DbLogType ) =~ m (history) ) {
my $ rv_ih = $ sth_ih - > execute ( ( $ timestamp , $ device , $ type , $ event , $ reading , $ value , $ unit ) ) ;
}
# update or insert current
if ( lc ( $ DbLogType ) =~ m (current) ) {
my $ rv_uc = $ sth_uc - > execute ( ( $ timestamp , $ type , $ event , $ value , $ unit , $ device , $ reading ) ) ;
if ( $ rv_uc == 0 ) {
my $ rv_ic = $ sth_ic - > execute ( ( $ timestamp , $ device , $ type , $ event , $ reading , $ value , $ unit ) ) ;
}
}
$ dbh - > commit ( ) ;
if ( $@ ) {
Log3 $ hash - > { NAME } , 2 , "DbLog: Failed to insert new readings into database: $@" ;
$ dbh - > { RaiseError } = 0 ;
$ dbh - > rollback ( ) ;
# reconnect
$ dbh - > disconnect ( ) ;
DbLog_Connect ( $ hash ) ;
}
else {
$ dbh - > { RaiseError } = 0 ;
}
return $ dbh - > { RaiseError } ;
}
################################################################
#
@@ -346,13 +401,11 @@ DbLog_ParseEvent($$$)
# aufgerufen
#
################################################################
sub
DbLog_Log ($$)
{
sub DbLog_Log ($$) {
# Log is my entry, Dev is the entry of the changed device
my ( $ log , $ dev ) = @ _ ;
my ( $ hash , $ dev ) = @ _ ;
return undef if ( $ log - > { STATE } eq "disabled" ) ;
return undef if ( $ hash - > { STATE } eq "disabled" ) ;
# name and type required for parsing
my $ n = $ dev - > { NAME } ;
@@ -362,25 +415,15 @@ DbLog_Log($$)
#my ($sec,$min,$hr,$day,$mon,$yr,$wday,$yday,$isdst)= localtime(time);
#my $ts= sprintf("%04d-%02d-%02d %02d:%02d:%02d", $yr+1900,$mon+1,$day,$hr,$min,$sec);
my $ re = $ log - > { REGEXP } ;
my $ re = $ hash - > { REGEXP } ;
my $ max = int ( @ { $ dev - > { CHANGED } } ) ;
my $ ts_0 = TimeNow ( ) ;
my $ now = gettimeofday ( ) ; # get timestamp in seconds since epoch
my $ DbLogExclude = AttrVal ( $ dev - > { NAME } , "DbLogExclude" , undef ) ;
my $ dbh = $ log - > { DBH } ;
$ dbh - > { RaiseError } = 1 ;
my $ DbLogType = AttrVal ( $ log - > { NAME } , "DbLogType" , "Current/History" ) ;
my $ DbLogType = AttrVal ( $ hash - > { NAME } , "DbLogType" , "Current/History" ) ;
#one Transaction
eval {
$ dbh - > begin_work ( ) ;
my $ sth_ih = $ dbh - > prepare_cached ( "INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)" ) if ( $ DbLogType =~ m (History) ) ;
my $ sth_uc = $ dbh - > prepare_cached ( "UPDATE current SET TIMESTAMP=?, TYPE=?, EVENT=?, VALUE=?, UNIT=? WHERE (DEVICE=?) AND (READING=?)" ) if ( $ DbLogType =~ m (Current) ) ;
my $ sth_ic = $ dbh - > prepare_cached ( "INSERT INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)" ) if ( $ DbLogType =~ m (Current) ) ;
# eval {
for ( my $ i = 0 ; $ i < $ max ; $ i + + ) {
my $ s = $ dev - > { CHANGED } [ $ i ] ;
$ s = "" if ( ! defined ( $ s ) ) ;
@@ -409,8 +452,8 @@ DbLog_Log($$)
$ DoIt = 0 if ( ! $ v2 [ 1 ] && $ reading =~ m/^$v2[0]$/ ) ; #Reading matcht auf Regexp, kein MinIntervall angegeben
if ( ( $ v2 [ 1 ] && $ reading =~ m/^$v2[0]$/ ) && ( $ v2 [ 1 ] =~ m/^(\d+)$/ ) ) {
#Regexp matcht und MinIntervall ist angegeben
my $ lt = $ defs { $ dev - > { NAME } } { Helper } { DBLOG } { $ reading } { $ log - > { NAME } } { TIME } ;
my $ lv = $ defs { $ dev - > { NAME } } { Helper } { DBLOG } { $ reading } { $ log - > { NAME } } { VALUE } ;
my $ lt = $ defs { $ dev - > { NAME } } { Helper } { DBLOG } { $ reading } { $ hash - > { NAME } } { TIME } ;
my $ lv = $ defs { $ dev - > { NAME } } { Helper } { DBLOG } { $ reading } { $ hash - > { NAME } } { VALUE } ;
$ lt = 0 if ( ! $ lt ) ;
$ lv = "" if ( ! $ lv ) ;
@@ -423,39 +466,14 @@ DbLog_Log($$)
}
next if ( $ DoIt == 0 ) ;
$ defs { $ dev - > { NAME } } { Helper } { DBLOG } { $ reading } { $ log - > { NAME } } { TIME } = $ now ;
$ defs { $ dev - > { NAME } } { Helper } { DBLOG } { $ reading } { $ log - > { NAME } } { VALUE } = $ value ;
$ defs { $ dev - > { NAME } } { Helper } { DBLOG } { $ reading } { $ hash - > { NAME } } { TIME } = $ now ;
$ defs { $ dev - > { NAME } } { Helper } { DBLOG } { $ reading } { $ hash - > { NAME } } { VALUE } = $ value ;
my @ is = ( $ ts , $ n , $ t , $ s , $ reading , $ value , $ unit ) ;
# insert into history
if ( $ DbLogType =~ m (History) ) {
my $ rv_ih = $ sth_ih - > execute ( @ is ) ;
}
if ( $ DbLogType =~ m (Current) ) {
# update or insert current
my $ rv_uc = $ sth_uc - > execute ( ( $ ts , $ t , $ s , $ value , $ unit , $ n , $ reading ) ) ;
if ( $ rv_uc == 0 ) {
my $ rv_ic = $ sth_ic - > execute ( @ is ) ;
}
}
DbLog_Push ( $ hash , $ DbLogType , $ ts , $ n , $ t , $ s , $ reading , $ value , $ unit )
}
}
$ dbh - > commit ( ) ;
} ;
if ( $@ ) {
Log3 $ dev - > { NAME } , 2 , "DbLog: Failed to insert new readings into database: $@" ;
$ dbh - > { RaiseError } = 0 ;
$ dbh - > rollback ( ) ;
# reconnect
$ dbh - > disconnect ( ) ;
DbLog_Connect ( $ log ) ;
}
else {
$ dbh - > { RaiseError } = 0 ;
}
#} ;
return "" ;
}
@@ -467,8 +485,7 @@ DbLog_Log($$)
# uebergebenes SQL-Format: YYYY-MM-DD HH24:MI:SS
#
################################################################
sub
DbLog_explode_datetime ($%) {
sub DbLog_explode_datetime ($%) {
my ( $ t , % def ) = @ _ ;
my % retv ;
@@ -489,20 +506,19 @@ DbLog_explode_datetime($%) {
return % retv
}
sub
DbLog_implode_datetime ($$$$$$) {
sub DbLog_implode_datetime ($$$$$$) {
my ( $ year , $ month , $ day , $ hour , $ minute , $ second ) = @ _ ;
my $ retv = $ year . "-" . $ month . "-" . $ day . " " . $ hour . ":" . $ minute . ":" . $ second ;
return $ retv ;
}
################################################################
#
# Verbindung zur DB aufbauen
#
################################################################
sub
DbLog_Connect ($)
sub DbLog_Connect ($)
{
my ( $ hash ) = @ _ ;
@@ -575,6 +591,9 @@ DbLog_Connect($)
#
# Prozeduren zum Ausfuehren des SQLs
#
# param1: hash
# param2: pointer : DBFilehandle
# param3: string : SQL
################################################################
sub
DbLog_ExecSQL1 ($$$)
@@ -618,6 +637,8 @@ DbLog_ExecSQL($$)
#
# GET Funktion
# wird zb. zur Generierung der Plots implizit aufgerufen
# infile : [-|current|history]
# outfile: [-|ALL|INT|WEBCHART]
#
################################################################
sub
@@ -632,16 +653,22 @@ DbLog_Get($@)
" <out> is a prefix, - means stdout\n"
if ( int ( @ a ) < 5 ) ;
shift @ a ;
my $ inf = shift @ a ;
my $ outf = shift @ a ;
my $ inf = lc ( shift @ a ) ;
my $ outf = lc ( shift @ a ) ;
my $ from = shift @ a ;
my $ to = shift @ a ; # Now @a contains the list of column_specs
my ( $ internal , @ fld ) ;
if ( $ out f eq "INT " ) {
if ( $ in f eq "- " ) {
$ inf = "history" ;
}
if ( $ outf eq "int" ) {
$ outf = "-" ;
$ internal = 1 ;
} elsif ( uc ( $ outf ) eq "WEBCHART " ) {
} elsif ( $ outf eq "array " ) {
} elsif ( uc ( $ outf ) eq "webchart" ) {
# redirect the get request to the chartQuery function
return chartQuery ( $ hash , @ _ ) ;
}
@@ -659,7 +686,8 @@ DbLog_Get($@)
$ to = $ to_datetime { datetime } ;
my ( $ retval , $ sql_timestamp , $ sql_value , $ type , $ event , $ unit ) = "" ;
my ( $ retval , $ sql_timestamp , $ sql_device , $ sql_reading , $ sql_value , $ type , $ event , $ unit ) = "" ;
my @ ReturnArray ;
my $ writeout = 0 ;
my ( @ min , @ max , @ sum , @ cnt , @ lastv , @ lastd ) ;
my ( % tstamp , % lasttstamp , $ out_tstamp , $ out_value , $ minval , $ maxval ) ; #fuer delta-h/d Berechnung
@@ -672,6 +700,8 @@ DbLog_Get($@)
$ readings [ $ i ] [ 2 ] = $ fld [ 2 ] ; # Default
$ readings [ $ i ] [ 3 ] = $ fld [ 3 ] ; # function
$ readings [ $ i ] [ 4 ] = $ fld [ 4 ] ; # regexp
$ readings [ $ i ] [ 1 ] = "%" if ( length ( $ readings [ $ i ] [ 1 ] ) == 0 ) ; #falls Reading nicht gef<65> llt setze Joker
}
#create new connection for plotfork
@@ -687,7 +717,7 @@ DbLog_Get($@)
$ sqlspec { get_timestamp } = "TO_CHAR(TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS')" ;
$ sqlspec { from_timestamp } = "TO_TIMESTAMP('$from', 'YYYY-MM-DD HH24:MI:SS')" ;
$ sqlspec { to_timestamp } = "TO_TIMESTAMP('$to', 'YYYY-MM-DD HH24:MI:SS')" ;
$ sqlspec{ reading_clause} = "(DEVICE || '|' || READING)" ;
#$ sqlspec{ reading_clause} = "(DEVICE || '|' || READING)";
} elsif ( $ hash - > { DBMODEL } eq "ORACLE" ) {
$ sqlspec { get_timestamp } = "TO_CHAR(TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS')" ;
$ sqlspec { from_timestamp } = "TO_TIMESTAMP('$from', 'YYYY-MM-DD HH24:MI:SS')" ;
@@ -706,7 +736,7 @@ DbLog_Get($@)
$ sqlspec { to_timestamp } = "'$to'" ;
}
if ( uc ( $ outf ) eq "ALL" ) {
if ( $ outf =~ m/(all|array)/ ) {
$ sqlspec { all } = ",TYPE,EVENT,UNIT" ;
} else {
$ sqlspec { all } = "" ;
@@ -724,33 +754,46 @@ DbLog_Get($@)
$ minval = 999999 ;
$ maxval = - 999999 ;
my $ stm = "SELECT
$sqlspec{get_timestamp},
VALUE
$sqlspec{all}
FROM history
WHER E
DEVICE = '" . $ readings [ $ i ] - > [ 0 ] . "'
AND READING = '" . $ readings [ $ i ] - > [ 1 ] . "'
AND TIMESTAMP > $sqlspec{from_timestamp}
AND TIMESTAMP < $sqlspec{to_timestamp}
ORDER BY TIMESTAMP" ;
my $ stm ;
$ stm = "SELECT
$sqlspec{get_timestamp},
DEVICE,
READING,
VALU E
$sqlspec{all} " ;
Log3 $ hash - > { NAME } , 5 , "Executing $stm" ;
$ stm . = "FROM current " if ( $ inf eq "current" ) ;
$ stm . = "FROM history " if ( $ inf eq "history" ) ;
$ stm . = "WHERE 1=1 " ;
$ stm . = "AND DEVICE = '" . $ readings [ $ i ] - > [ 0 ] . "' " if ( $ readings [ $ i ] - > [ 0 ] !~ m (\%) ) ;
$ stm . = "AND DEVICE LIKE '" . $ readings [ $ i ] - > [ 0 ] . "' " if ( ( $ readings [ $ i ] - > [ 0 ] !~ m (^\%$) ) && ( $ readings [ $ i ] - > [ 0 ] =~ m (\%) ) ) ;
$ stm . = "AND READING = '" . $ readings [ $ i ] - > [ 1 ] . "' " if ( $ readings [ $ i ] - > [ 1 ] !~ m (\%) ) ;
$ stm . = "AND READING LIKE '" . $ readings [ $ i ] - > [ 1 ] . "' " if ( ( $ readings [ $ i ] - > [ 1 ] !~ m (^%$) ) && ( $ readings [ $ i ] - > [ 1 ] =~ m (\%) ) ) ;
$ stm . = "AND TIMESTAMP > $sqlspec{from_timestamp}
AND TIMESTAMP < $sqlspec{to_timestamp}
ORDER BY TIMESTAMP" ;
Log3 $ hash - > { NAME } , 4 , "Processing Statement: $stm" ;
my $ sth = $ dbh - > prepare ( $ stm ) ||
return "Cannot prepare statement $stm: $DBI::errstr" ;
my $ rc = $ sth - > execute ( ) ||
return "Cannot execute statement $stm: $DBI::errstr" ;
if ( uc ( $ outf ) eq "ALL" ) {
$ sth - > bind_columns ( undef , \ $ sql_timestamp , \ $ sql_value , \ $ type , \ $ event , \ $ unit ) ;
$ retval . = "Timestamp: Device, Type, Event, Reading, Value, Unit\n" ;
$ retval . = "=====================================================\n" ;
if ( $ outf =~ m/(all|array)/ ) {
$ sth - > bind_columns ( undef , \ $ sql_timestamp , \ $ sql_device , \ $ sql_reading , \ $ sql_value , \ $ type , \ $ event , \ $ unit ) ;
}
else {
$ sth - > bind_columns ( undef , \ $ sql_timestamp , \ $ sql_value ) ;
$ sth - > bind_columns ( undef , \ $ sql_timestamp , \ $ sql_value ) ;
}
if ( $ outf =~ m/(all)/ ) {
$ retval . = "Timestamp: Device, Type, Event, Reading, Value, Unit\n" ;
$ retval . = "=====================================================\n" ;
}
while ( $ sth - > fetch ( ) ) {
@@ -840,8 +883,13 @@ DbLog_Get($@)
###################### Ausgabe ###########################
if ( $ writeout ) {
if ( uc ( $ outf ) eq "ALL" ) {
$ retval . = sprintf ( "%s: %s, %s, %s, %s, %s, %s\n" , $ out_tstamp , $ readings [ $ i ] - > [ 0 ] , $ type , $ event , $ readings [ $ i ] - > [ 1 ] , $ out_value , $ unit ) ;
if ( $ outf =~ m/(all)/ ) {
# Timestamp: Device, Type, Event, Reading, Value, Unit
$ retval . = sprintf ( "%s: %s, %s, %s, %s, %s, %s\n" , $ out_tstamp , $ sql_device , $ type , $ event , $ sql_reading , $ out_value , $ unit ) ;
} elsif ( $ outf =~ m/(array)/ ) {
push ( @ ReturnArray , { "tstamp" = > $ out_tstamp , "device" = > $ sql_device , "type" = > $ type , "event" = > $ event , "reading" = > $ sql_reading , "value" = > $ out_value , "unit" = > $ unit } ) ;
} else {
$ out_tstamp =~ s/\ /_/g ; #needed by generating plots
$ retval . = "$out_tstamp $out_value\n" ;
@@ -873,12 +921,17 @@ DbLog_Get($@)
$ out_value = sprintf ( "%g" , $ 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" ) ;
if ( uc ( $ outf ) eq "ALL" ) {
$ retval . = sprintf ( "%s: %s %s %s %s %s %s\n" , $ out_tstamp , $ readings [ $ i ] - > [ 0 ] , $ type , $ event , $ readings [ $ i ] - > [ 1 ] , $ out_value , $ unit ) ;
} else {
$ out_tstamp =~ s/\ /_/g ; #needed by generating plots
$ retval . = "$out_tstamp $out_value\n" ;
}
if ( $ outf =~ m/(all)/ ) {
$ retval . = sprintf ( "%s: %s %s %s %s %s %s\n" , $ out_tstamp , $ sql_device , $ type , $ event , $ sql_reading , $ out_value , $ unit ) ;
} elsif ( $ outf =~ m/(array)/ ) {
push ( @ ReturnArray , { "tstamp" = > $ out_tstamp , "device" = > $ sql_device , "type" = > $ type , "event" = > $ event , "reading" = > $ sql_reading , "value" = > $ out_value , "unit" = > $ unit } ) ;
} else {
$ out_tstamp =~ s/\ /_/g ; #needed by generating plots
$ retval . = "$out_tstamp $out_value\n" ;
}
}
# DatenTrenner setzen
$ retval . = "#$readings[$i]->[0]" ;
@@ -911,8 +964,13 @@ DbLog_Get($@)
if ( $ internal ) {
$ internal_data = \ $ retval ;
return undef ;
} elsif ( $ outf =~ m/(array)/ ) {
return @ ReturnArray ;
} else {
return $ retval ;
}
return $ retval ;
}
################################################################
@@ -1240,18 +1298,17 @@ sub chartQuery($@) {
contains the last event for any given reading and device.
The columns have the following meaning:
<ol>
<li>TIMESTAMP: timestamp of event, e.g. <code>2007-12-30 21:45:22</code></li>
<li>DEVICE: device name, e.g. <code>Wetterstation</code></li>
<li>TYPE: device type, e.g. <code>KS300</code></li>
<li>EVENT: event specification as full string,
e.g. <code>humidity: 71 (%)</code></li>
<li>READING: name of reading extracted from event,
e.g. <code>humidity</code></li>
<li>TIMESTAMP: timestamp of event, e.g. <code>2007-12-30 21:45:22</code></li>
<li>DEVICE: device name, e.g. <code>Wetterstation </code></li>
<li>TYPE: device type , e.g. <code>KS300 </code></li>
<li>EVENT: event specification as full string,
e.g. <code>humidity: 71 (%)</code></li>
<li>READING: name of reading extracted from event,
e.g. <code>humidity</code></li>
<li>VALUE: actual reading extracted from event,
e.g. <code>71</code></li>
<li>UNIT: unit extracted from event, e.g. <code>%</code></li>
<li>VALUE: actual reading extracted from event,
e.g. <code>71 </code></li>
<li>UNIT: unit extracted from event , e.g. <code>% </code></li>
</ol>
The content of VALUE is optimized for automated post-processing, e.g.
<code>yes</code> is translated to <code>1</code>
@@ -1284,11 +1341,25 @@ sub chartQuery($@) {
<ul>
<li><in><br>
A dummy parameter for FileLog compatibility. Always set to <code>-</code></li >
A dummy parameter for FileLog compatibility. Sessing by default to <code>-</code><br >
<ul>
<li>current: reading actual readings from table "current"</li>
<li>history: reading history readings from table "history"</li>
<li>-: identical to "history"</li>
</ul>
</li>
<li><out><br>
A dummy parameter for FileLog compatibility. Set i t to <code>-</code>
to check the output for plot-computing.<br>Set it to the special keyword
<code>all</code> to get all columns from Database.</li>
A dummy parameter for FileLog compatibility. Setting by defaul t to <code>-</code>
to check the output for plot-computing.<br>
Set it to the special keyword
<code>all</code> to get all columns from Database.
<ul>
<li>ALL: get all colums from table, including a header</li>
<li>Array: get the columns as array of hashes</li>
<li>INT: internally used by generating plots</li>
<li>-: default</li>
</ul>
</li>
<li><from> / <to><br>
Used to select the data. Please use the following timeformat or
an initial substring of it:<br>
@@ -1299,9 +1370,9 @@ sub chartQuery($@) {
Syntax: <device>:<reading>:<default>:<fn>:<regexp><br>
<ul>
<li><device><br>
The name of the device. Case sensitive</li>
The name of the device. Case sensitive. Using a the joker "%" is supported. </li>
<li><reading><br>
The reading of the given device to select. Case sensitive.
The reading of the given device to select. Case sensitive. Using a the joker "%" is supported.
</li>
<li><default><br>
no implemented yet
@@ -1344,6 +1415,9 @@ sub chartQuery($@) {
Examples:
<ul>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 KS300:temperature</code></li>
<li><code>get myDbLog current ALL - - %:temperature</code></li><br>
you will get all actual readings "temperature" from all logged devices.
Be carful by using "history" as inputfile because a long execution time will be expected!
<li><code>get myDbLog - - 2012-11-10_10 2012-11-10_20 KS300:temperature::int1</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>
@@ -1472,13 +1546,13 @@ sub chartQuery($@) {
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>
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>
mö ssen installiert werden (use <code>cpan -i <module></code>
falls die eigene Distribution diese nicht schon mitbringt).
<br><br>
@@ -1487,28 +1561,28 @@ sub chartQuery($@) {
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
<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>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>
<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
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:
Die gespeicherten Werte kö nnen mittels GET Funktion angezeigt werden:
<ul>
<code>get myDbLog - - 2012-11-10 2012-11-10 KS300:temperature</code>
</ul>
@@ -1516,7 +1590,6 @@ sub chartQuery($@) {
<b>Beispiel:</b>
<ul>
<code>Speichert alles in der Datenbank</code><br>
<code>define myDbLog DbLog /etc/fhem/db.conf .*:.*</code>
</ul>
</ul>
@@ -1531,37 +1604,49 @@ sub chartQuery($@) {
<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.
Liess 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.
Ein Parameter um eine Kompatibilitä t zum Filelog herzustellen.
Dieser Parameter ist per default immer auf <code>-</code> zu setzen.<br>
Folgende Ausprägungen sind zugelassen:<br>
<ul>
<li>current: die aktuellen Werte aus der Tabelle "current" werden gelesen.</li>
<li>history: die historischen Werte aus der Tabelle "history" werden gelesen.</li>
<li>-: identisch wie "history"</li>
</ul>
</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>
Ein Parameter um eine Kompatibilitä t zum Filelog herzustellen.
Dieser Parameter ist per default immer auf <code>-</code> zu setzen um die
Ermittlung der Daten aus der Datenbank fö r die Plotgenerierung zu prö fen.<br>
Folgende Ausprägungen sind zugelassen:<br>
<ul>
<li>ALL: Es werden alle Spalten der Datenbank ausgegeben. Inclusive einer Überschrift.< /li>
<li>Array: Es werden alle Spalten der Datenbank als Hash ausgegeben. Alle Datensätze als Array zusammengefasst.</li>
<li>INT: intern zur Plotgenerierung verwendet</li>
<li>-: default</li>
</ul>
</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
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 >
Der Name des Devices. Achtung: Gross /Kleinschreibung beachten!<br >
Es kann ein % als Jokerzeichen angegeben werden.</li>
<li><reading><br>
Das RE ading des angegebenen Devices zur Datenselektion.
Achtung: Groß/Kleinschreibung beachten!
Das Re ading des angegebenen Devices zur Datenselektion.<br>
Es kann ein % als Jokerzeichen angegeben werden.<br>
Achtung: Gross/Kleinschreibung beachten!
</li>
<li><default><br>
Zur Zeit noch nicht implementiert.
@@ -1571,17 +1656,17 @@ sub chartQuery($@) {
<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%.
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.
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
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>
<li>delta-ts<br>
@@ -1590,19 +1675,19 @@ sub chartQuery($@) {
</li>
</ul></li>
<li><regexp><br>
Diese Zeichenkette wird als Perl Befehl ausgewertet. Die regexp wird vor dem angegebenen <fn> Parameter ausgefü hrt.
Diese Zeichenkette wird als Perl Befehl ausgewertet. 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.<br>
<b>Schlüsselwö rter</b>
<li>$val ist der aktuelle Wert die die Datenbank fü r ein Device/Reading ausgibt.</li>
<b>Schlösselwö rter</b>
<li>$val ist der aktuelle Wert die die Datenbank fö r ein Device/Reading ausgibt.</li>
<li>$ts ist der aktuelle Timestamp des Logeintrages.</li>
<li>Wird als $val das Schlü sselwort "hide" zurü ckgegeben, so wird dieser Logeintrag nicht
ausgegeben, trotzdem aber fü r die Zeitraumberechnung verwendet.</li>
<li>Wird als $val das Schlü sselwort "ignore" zurü ckgegeben, so wird dieser Logeintrag
nicht fü r eine Folgeberechnung verwendet.</li>
<li>Wird als $val das Schlö sselwort "hide" zurö ckgegeben, so wird dieser Logeintrag nicht
ausgegeben, trotzdem aber fö r die Zeitraumberechnung verwendet.</li>
<li>Wird als $val das Schlö sselwort "ignore" zurö ckgegeben, so wird dieser Logeintrag
nicht fö r eine Folgeberechnung verwendet.</li>
</li>
</ul></li>
</ul>
@@ -1610,39 +1695,42 @@ sub chartQuery($@) {
<b>Beispiele:</b>
<ul>
<li><code>get myDbLog - - 2012-11-10 2012-11-20 KS300:temperature</code></li>
<li><code>get myDbLog current ALL - - %:temperature</code></li><br>
Damit erh<72> lt man alle aktuellen Readings "temperature" von allen in der DB geloggten Devices.
Achtung: bei Nutzung von Jokerzeichen auf die historyTabelle kann man sein FHEM aufgrund langer Laufzeit lahmlegen!
<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>
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>
und die Ausgabe ist fö r das Reading B folgende: <code>2012-11-20_10:23:54 66.647</code></li>
<li><code>get DbLog - - 2013-05-26 2013-05-28 Pumpe:data::delta-ts:$val=~s/on/hide/</code><br>
Realisierung eines Betriebsstundenzä hlers.Durch delta-ts wird die Zeit in Sek zwischen den Log-
einträ gen ermittelt. Die Zeiten werden bei den on-Meldungen nicht ausgegeben welche einer Abschaltzeit
entsprechen wü rden.</li>
Realisierung eines Betriebsstundenzä hlers.Durch delta-ts wird die Zeit in Sek zwischen den Log-
einträ gen ermittelt. Die Zeiten werden bei den on-Meldungen nicht ausgegeben welche einer Abschaltzeit
entsprechen wö rden.</li>
</ul>
<br><br>
</ul>
<b>Get</b> fü r die Nutzung von webcharts
<b>Get</b> fö r die Nutzung von webcharts
<ul>
<code>get <name> <infile> <outfile> <from>
<to> <device> <querytype> <xaxis> <yaxis> <savename> </code>
<br><br>
Liest Daten aus der Datenbank aus und gibt diese in JSON formatiert aus. Wird fü r das Charting Frontend genutzt
Liest Daten aus der Datenbank aus und gibt diese in JSON formatiert aus. Wird fö r das Charting Frontend genutzt
<br>
<ul>
<li><name><br>
Der Name des definierten DbLogs, so wie er in der fhem.cfg angegeben wurde.</li>
<li><in><br>
Ein Dummy Parameter um eine Kompatibilitä t zum Filelog herzustellen.
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.
Ein Dummy Parameter um eine Kompatibilitä t zum Filelog herzustellen.
Dieser Parameter ist auf <code>webchart</code> zu setzen um die Charting Get Funktion zu nutzen.
</li>
<li><from> / <to><br>
@@ -1652,32 +1740,32 @@ sub chartQuery($@) {
<li><device><br>
Ein String, der das abzufragende Device darstellt.</li>
<li><querytype><br>
Ein String, der die zu verwendende Abfragemethode darstellt. Zur Zeit unterstü tzte Werte sind: <br>
<code>getreadings</code> um fü r ein bestimmtes device alle Readings zu erhalten<br>
<code>getdevices</code> um alle verfü gbaren devices zu erhalten<br>
<code>timerange</code> um Chart-Daten abzufragen. Es werden die Parameter 'xaxis', 'yaxis', 'device', 'to' und 'from' benö tigt<br>
<code>savechart</code> um einen Chart unter Angabe eines 'savename' und seiner zugehö rigen Konfiguration abzuspeichern<br>
<code>deletechart</code> um einen zuvor gespeicherten Chart unter Angabe einer id zu lö schen<br>
Ein String, der die zu verwendende Abfragemethode darstellt. Zur Zeit unterstö tzte Werte sind: <br>
<code>getreadings</code> um fö r ein bestimmtes device alle Readings zu erhalten<br>
<code>getdevices</code> um alle verfö gbaren devices zu erhalten<br>
<code>timerange</code> um Chart-Daten abzufragen. Es werden die Parameter 'xaxis', 'yaxis', 'device', 'to' und 'from' benö tigt<br>
<code>savechart</code> um einen Chart unter Angabe eines 'savename' und seiner zugehö rigen Konfiguration abzuspeichern<br>
<code>deletechart</code> um einen zuvor gespeicherten Chart unter Angabe einer id zu lö schen<br>
<code>getcharts</code> um eine Liste aller gespeicherten Charts zu bekommen.<br>
<code>getTableData</code> um Daten aus der Datenbank abzufragen und in einer Tabelle darzustellen. Benö tigt paging Parameter wie start und limit.<br>
<code>hourstats</code> um Statistiken fü r einen Wert (yaxis) fü r eine Stunde abzufragen.<br>
<code>daystats</code> um Statistiken fü r einen Wert (yaxis) fü r einen Tag abzufragen.<br>
<code>weekstats</code> um Statistiken fü r einen Wert (yaxis) fü r eine Woche abzufragen.<br>
<code>monthstats</code> um Statistiken fü r einen Wert (yaxis) fü r einen Monat abzufragen.<br>
<code>yearstats</code> um Statistiken fü r einen Wert (yaxis) fü r ein Jahr abzufragen.<br>
<code>getTableData</code> um Daten aus der Datenbank abzufragen und in einer Tabelle darzustellen. Benö tigt paging Parameter wie start und limit.<br>
<code>hourstats</code> um Statistiken fö r einen Wert (yaxis) fö r eine Stunde abzufragen.<br>
<code>daystats</code> um Statistiken fö r einen Wert (yaxis) fö r einen Tag abzufragen.<br>
<code>weekstats</code> um Statistiken fö r einen Wert (yaxis) fö r eine Woche abzufragen.<br>
<code>monthstats</code> um Statistiken fö r einen Wert (yaxis) fö r einen Monat abzufragen.<br>
<code>yearstats</code> um Statistiken fö r einen Wert (yaxis) fö r ein Jahr abzufragen.<br>
</li>
<li><xaxis><br>
Ein String, der die X-Achse reprä sentiert</li>
Ein String, der die X-Achse reprä sentiert</li>
<li><yaxis><br>
Ein String, der die Y-Achse reprä sentiert</li>
Ein String, der die Y-Achse reprä sentiert</li>
<li><savename><br>
Ein String, unter dem ein Chart in der Datenbank gespeichert werden soll</li>
<li><chartconfig><br>
Ein jsonstring der den zu speichernden Chart reprä sentiert</li>
Ein jsonstring der den zu speichernden Chart reprä sentiert</li>
<li><pagingstart><br>
Ein Integer um den Startwert fü r die Abfrage 'getTableData' festzulegen</li>
Ein Integer um den Startwert fö r die Abfrage 'getTableData' festzulegen</li>
<li><paginglimit><br>
Ein Integer um den Limitwert fü r die Abfrage 'getTableData' festzulegen</li>
Ein Integer um den Limitwert fö r die Abfrage 'getTableData' festzulegen</li>
</ul>
<br><br>
Beispiele:
@@ -1685,16 +1773,16 @@ sub chartQuery($@) {
<li><code>get logdb - webchart "" "" "" getcharts</code><br>
Liefert alle gespeicherten Charts aus der Datenbank</li>
<li><code>get logdb - webchart "" "" "" getdevices</code><br>
Liefert alle verfü gbaren Devices aus der Datenbank</li>
Liefert alle verfö gbaren Devices aus der Datenbank</li>
<li><code>get logdb - webchart "" "" ESA2000_LED_011e getreadings</code><br>
Liefert alle verfü gbaren Readings aus der Datenbank unter Angabe eines Gerä tes</li>
Liefert alle verfö gbaren Readings aus der Datenbank unter Angabe eines Gerä tes</li>
<li><code>get logdb - webchart 2013-02-11_00:00:00 2013-02-12_00:00:00 ESA2000_LED_011e timerange TIMESTAMP day_kwh</code><br>
Liefert Chart-Daten, die auf folgenden Parametern basieren: 'xaxis', 'yaxis', 'device', 'to' und 'from'<br>
Die Ausgabe erfolgt als JSON, z.B.: <code>[{'TIMESTAMP':'2013-02-11 00:10:10','VALUE':'0.22431388090756'},{'TIMESTAMP'.....}]</code></li>
<li><code>get logdb - webchart 2013-02-11_00:00:00 2013-02-12_00:00:00 ESA2000_LED_011e savechart TIMESTAMP day_kwh tageskwh</code><br>
Speichert einen Chart unter Angabe eines 'savename' und seiner zugehö rigen Konfiguration</li>
Speichert einen Chart unter Angabe eines 'savename' und seiner zugehö rigen Konfiguration</li>
<li><code>get logdb - webchart "" "" "" deletechart "" "" 7</code><br>
Lö scht einen zuvor gespeicherten Chart unter Angabe einer id</li>
Lö scht einen zuvor gespeicherten Chart unter Angabe einer id</li>
</ul>
<br><br>
</ul>
@@ -1709,11 +1797,11 @@ sub chartQuery($@) {
</ul>
<br>
Wenn DbLog genutzt wird, wird in alle Devices das Attribut <i>DbLogExclude</i>
propagiert. Der Wert des Attributes wird als Regexp ausgewertet und schließ t die
propagiert. Der Wert des Attributes wird als Regexp ausgewertet und schliess t die
damit matchenden Readings von einem Logging aus. Einzelne Regexp werden durch
Kommata getrennt. Ist MinIntervall angegeben, so wird der Logeintrag nur
dann nicht geloggt, wenn das Intervall noch nicht erreicht und der Wert des
Readings sich nicht verä ndert hat.
Readings sich nicht verä ndert hat.
<br>
<b>Beispiele</b>
<ul>