93_DbLog.pm: stable release in contrib copied to main folder

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@3031 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
tobiasfaust 2013-04-04 11:37:17 +00:00
parent c542130593
commit 41b4dce1e4
2 changed files with 250 additions and 1646 deletions

View File

@ -30,7 +30,7 @@ DbLog_Initialize($)
$hash->{NotifyFn} = "DbLog_Log"; $hash->{NotifyFn} = "DbLog_Log";
$hash->{GetFn} = "DbLog_Get"; $hash->{GetFn} = "DbLog_Get";
$hash->{AttrFn} = "DbLog_Attr"; $hash->{AttrFn} = "DbLog_Attr";
$hash->{AttrList} = "disable:0,1 loglevel:0,5"; $hash->{AttrList} = "disable:0,1 loglevel:0,5 DbLogType:Current,History,Current/History";
} }
@ -120,7 +120,6 @@ DbLog_ParseEvent($$)
($type eq "M232Counter") || ($type eq "M232Counter") ||
($type eq "EMEM")) { ($type eq "EMEM")) {
} }
# Onewire # Onewire
elsif(($type eq "OWAD") || elsif(($type eq "OWAD") ||
($type eq "OWSWITCH") || ($type eq "OWSWITCH") ||
@ -131,16 +130,15 @@ DbLog_ParseEvent($$)
# FS20 # FS20
elsif(($type eq "FS20") || elsif(($type eq "FS20") ||
($type eq "X10")) { ($type eq "X10")) {
#@parts = split(/ /,$event);
#$reading = shift @parts;
#$value = join(" ", shift @parts);
if($reading =~ m/^dim(\d+).*/o) { if($reading =~ m/^dim(\d+).*/o) {
$value = $1; $value = $1;
$reading= "dim"; $reading= "dim";
$unit= "%"; $unit= "%";
} }
if(!defined($value) || $value eq "") {$value=$reading; $reading="data";} elsif(!defined($value) || $value eq "") {
$value= $reading;
$reading= "data";
}
} }
# FHT # FHT
elsif($type eq "FHT") { elsif($type eq "FHT") {
@ -150,9 +148,9 @@ DbLog_ParseEvent($$)
$value= $parts[1]; $value= $parts[1];
$unit= ""; $unit= "";
} }
if($reading =~ m(-temp)) { $value=~ s/ \(Celsius\)//; $unit= "°C"; } elsif($reading =~ m(-temp)) { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
if($reading =~ m(temp-offset)) { $value=~ s/ \(Celsius\)//; $unit= "°C"; } elsif($reading =~ m(temp-offset)) { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
if($reading =~ m(^actuator[0-9]*)) { elsif($reading =~ m(^actuator[0-9]*)) {
if($value eq "lime-protection") { if($value eq "lime-protection") {
$reading= "actuator-lime-protection"; $reading= "actuator-lime-protection";
undef $value; undef $value;
@ -193,14 +191,14 @@ DbLog_ParseEvent($$)
# KS300 # KS300
elsif($type eq "KS300") { elsif($type eq "KS300") {
if($event =~ m(T:.*)) { $reading= "data"; $value= $event; } if($event =~ m(T:.*)) { $reading= "data"; $value= $event; }
if($event =~ m(avg_day)) { $reading= "data"; $value= $event; } elsif($event =~ m(avg_day)) { $reading= "data"; $value= $event; }
if($event =~ m(avg_month)) { $reading= "data"; $value= $event; } elsif($event =~ m(avg_month)) { $reading= "data"; $value= $event; }
if($reading eq "temperature") { $value=~ s/ \(Celsius\)//; $unit= "°C"; } elsif($reading eq "temperature") { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
if($reading eq "wind") { $value=~ s/ \(km\/h\)//; $unit= "km/h"; } elsif($reading eq "wind") { $value=~ s/ \(km\/h\)//; $unit= "km/h"; }
if($reading eq "rain") { $value=~ s/ \(l\/m2\)//; $unit= "l/m2"; } elsif($reading eq "rain") { $value=~ s/ \(l\/m2\)//; $unit= "l/m2"; }
if($reading eq "rain_raw") { $value=~ s/ \(counter\)//; $unit= ""; } elsif($reading eq "rain_raw") { $value=~ s/ \(counter\)//; $unit= ""; }
if($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; } elsif($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; }
if($reading eq "israining") { elsif($reading eq "israining") {
$value=~ s/ \(yes\/no\)//; $value=~ s/ \(yes\/no\)//;
$value=~ s/no/0/; $value=~ s/no/0/;
$value=~ s/yes/1/; $value=~ s/yes/1/;
@ -211,16 +209,23 @@ DbLog_ParseEvent($$)
$type eq "CUL_WS" || $type eq "CUL_WS" ||
$type eq "OWTHERM") { $type eq "OWTHERM") {
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"; } elsif($reading eq "temperature") {
if($reading eq "temperature") { $value=~ s/([-\.\d]+).*/$1/; $unit= "°C"; } #OWTHERM $value=~ s/ \(Celsius\)//;
if($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; } $value=~ s/([-\.\d]+).*/$1/; #OWTHERM
if($reading eq "battery") { $unit= "°C";
}
elsif($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; }
elsif($reading eq "battery") {
$value=~ s/ok/1/; $value=~ s/ok/1/;
$value=~ s/replaced/1/; $value=~ s/replaced/1/;
$value=~ s/empty/0/; $value=~ s/empty/0/;
} }
} }
# CUL_HM
elsif ($type eq "CUL_HM") {
# remove trailing %
$value=~ s/ \%$//;
}
# BS # BS
elsif($type eq "BS") { elsif($type eq "BS") {
if($event =~ m(brightness:.*)) { if($event =~ m(brightness:.*)) {
@ -230,7 +235,26 @@ DbLog_ParseEvent($$)
$unit= "lux"; $unit= "lux";
} }
} }
# RFXTRX Lighting
elsif($type eq "TRX_LIGHT") {
if($reading =~ m/^level (\d+)/) {
$value = $1;
$reading= "level";
}
}
# RFXTRX Sensors
elsif($type eq "TRX_WEATHER") {
if($reading eq "energy_current") { $value=~ s/ W//; }
elsif($reading eq "energy_total") { $value=~ s/ kWh//; }
elsif($reading eq "battery") {
if ($value=~ m/(\d+)\%/) {
$value= $1;
}
else {
$value= ($value eq "ok");
}
}
}
# Weather # Weather
elsif($type eq "WEATHER") { elsif($type eq "WEATHER") {
if($event =~ m(^wind_condition)) { if($event =~ m(^wind_condition)) {
@ -238,16 +262,32 @@ DbLog_ParseEvent($$)
if(defined $parts[0]) { if(defined $parts[0]) {
$reading = "wind_direction"; $reading = "wind_direction";
$value= $parts[2]; $value= $parts[2];
# $unit= "";
} }
} }
if($reading =~ m(^wind)) { $unit= "km/h"; } # wind, wind_speed elsif($reading eq "wind_chill") { $unit= "°C"; }
if($reading eq "wind_chill") { $unit= "°C"; } elsif($reading eq "wind_direction") { $unit= ""; }
if($reading eq "wind_direction") { $unit= ""; } elsif($reading =~ m(^wind)) { $unit= "km/h"; } # wind, wind_speed
if($reading =~ m(^temperature)) { $unit= "°C"; } # wenn reading mit temperature beginnt elsif($reading =~ m(^temperature)) { $unit= "°C"; } # wenn reading mit temperature beginnt
if($reading =~ m(^humidity)) { $unit= "%"; } elsif($reading =~ m(^humidity)) { $unit= "%"; }
if($reading =~ m(^pressure)) { $unit= "hPa"; } elsif($reading =~ m(^pressure)) { $unit= "hPa"; }
if($reading =~ m(^pressure_trend)) { $unit= ""; } elsif($reading =~ m(^pressure_trend)) { $unit= ""; }
}
# FHT8V
elsif($type eq "FHT8V") {
if($reading =~ m(valve)) {
@parts= split(/ /,$event);
$reading= $parts[0];
$value= $parts[1];
$unit= "%";
}
}
# DUMMY
elsif($type eq "DUMMY") {
$reading= "data";
$value= $event;
$unit= "";
} }
@result= ($reading,$value,$unit); @result= ($reading,$value,$unit);
@ -279,11 +319,26 @@ DbLog_Log($$)
my $re = $log->{REGEXP}; my $re = $log->{REGEXP};
my $max = int(@{$dev->{CHANGED}}); my $max = int(@{$dev->{CHANGED}});
my $ts_0 = TimeNow();
my $dbh= $log->{DBH};
$dbh->{RaiseError} = 1;
my $DbLogType = AttrVal($log->{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) );
for (my $i = 0; $i < $max; $i++) { for (my $i = 0; $i < $max; $i++) {
my $s = $dev->{CHANGED}[$i]; my $s = $dev->{CHANGED}[$i];
$s = "" if(!defined($s)); $s = "" if(!defined($s));
if($n =~ m/^$re$/ || "$n:$s" =~ m/^$re$/) { if($n =~ m/^$re$/ || "$n:$s" =~ m/^$re$/) {
my $ts = TimeNow(); my $ts = $ts_0;
$ts = $dev->{CHANGETIME}[$i] if(defined($dev->{CHANGETIME}[$i])); $ts = $dev->{CHANGETIME}[$i] if(defined($dev->{CHANGETIME}[$i]));
# $ts is in SQL format YYYY-MM-DD hh:mm:ss # $ts is in SQL format YYYY-MM-DD hh:mm:ss
@ -297,16 +352,36 @@ DbLog_Log($$)
$unit = AttrVal("$n", "unit", ""); $unit = AttrVal("$n", "unit", "");
} }
my $is= "(TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES " . my @is= ($ts, $n, $t, $s, $reading, $value, $unit);
"('$ts', '$n', '$t', '$s', '$reading', '$value', '$unit')";
DbLog_ExecSQL($log, "INSERT INTO history" . $is);
DbLog_ExecSQL($log, "DELETE FROM current WHERE (DEVICE='$n') AND (READING='$reading')");
DbLog_ExecSQL($log, "INSERT INTO current" . $is);
# 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);
}
}
} }
} }
$dbh->commit();
};
if ($@) {
Log 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 ""; return "";
} }
@ -400,8 +475,9 @@ DbLog_Connect($)
$dbh->do("PRAGMA temp_store=MEMORY"); $dbh->do("PRAGMA temp_store=MEMORY");
$dbh->do("PRAGMA synchronous=NORMAL"); $dbh->do("PRAGMA synchronous=NORMAL");
$dbh->do("PRAGMA journal_mode=WAL"); $dbh->do("PRAGMA journal_mode=WAL");
$dbh->do("CREATE TEMP TABLE IF NOT EXISTS current (TIMESTAMP TIMESTAMP, DEVICE varchar(32), TYPE varchar(32), EVENT varchar(512), READING varchar(32), VALUE varchar(32), UNIT varchar(32))"); $dbh->do("PRAGMA cache_size=4000");
$dbh->do("CREATE TABLE IF NOT EXISTS history (TIMESTAMP TIMESTAMP, DEVICE varchar(32), TYPE varchar(32), EVENT varchar(512), READING varchar(32), VALUE varchar(32), UNIT varchar(32))"); $dbh->do("CREATE TEMP TABLE IF NOT EXISTS current (TIMESTAMP TIMESTAMP, DEVICE varchar(32), TYPE varchar(32), EVENT varchar(512), READING varchar(32), VALUE varchar(32), UNIT varchar(32)");
$dbh->do("CREATE TABLE IF NOT EXISTS history (TIMESTAMP TIMESTAMP, DEVICE varchar(32), TYPE varchar(32), EVENT varchar(512), READING varchar(32), VALUE varchar(32), UNIT varchar(32)");
$dbh->do("CREATE INDEX IF NOT EXISTS Search_Idx ON `history` (DEVICE, READING, TIMESTAMP)"); $dbh->do("CREATE INDEX IF NOT EXISTS Search_Idx ON `history` (DEVICE, READING, TIMESTAMP)");
} }
@ -506,7 +582,7 @@ DbLog_Get($@)
$to = $to_datetime{datetime}; $to = $to_datetime{datetime};
my ($retval,$sql_timestamp,$sql_dev,$sql_reading,$sql_value, $type, $event, $unit) = ""; my ($retval,$sql_timestamp,$sql_value, $type, $event, $unit) = "";
my $writeout = 0; my $writeout = 0;
my (@min, @max, @sum, @cnt, @lastv, @lastd); my (@min, @max, @sum, @cnt, @lastv, @lastd);
my (%tstamp, %lasttstamp, $out_tstamp, $out_value, $minval, $maxval); #fuer delta-h/d Berechnung my (%tstamp, %lasttstamp, $out_tstamp, $out_value, $minval, $maxval); #fuer delta-h/d Berechnung
@ -533,22 +609,18 @@ DbLog_Get($@)
$sqlspec{get_timestamp} = "TO_CHAR(TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS')"; $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{from_timestamp} = "TO_TIMESTAMP('$from', 'YYYY-MM-DD HH24:MI:SS')";
$sqlspec{to_timestamp} = "TO_TIMESTAMP('$to', 'YYYY-MM-DD HH24:MI:SS')"; $sqlspec{to_timestamp} = "TO_TIMESTAMP('$to', 'YYYY-MM-DD HH24:MI:SS')";
$sqlspec{reading_clause} = "(DEVICE || '|' || READING)";
} elsif ($hash->{DBMODEL} eq "MYSQL") { } elsif ($hash->{DBMODEL} eq "MYSQL") {
$sqlspec{get_timestamp} = "DATE_FORMAT(TIMESTAMP, '%Y-%m-%d %H:%i:%s')"; $sqlspec{get_timestamp} = "DATE_FORMAT(TIMESTAMP, '%Y-%m-%d %H:%i:%s')";
$sqlspec{from_timestamp} = "STR_TO_DATE('$from', '%Y-%m-%d %H:%i:%s')"; $sqlspec{from_timestamp} = "STR_TO_DATE('$from', '%Y-%m-%d %H:%i:%s')";
$sqlspec{to_timestamp} = "STR_TO_DATE('$to', '%Y-%m-%d %H:%i:%s')"; $sqlspec{to_timestamp} = "STR_TO_DATE('$to', '%Y-%m-%d %H:%i:%s')";
$sqlspec{reading_clause} = "CONCAT(DEVICE,'|',READING)"
} elsif ($hash->{DBMODEL} eq "SQLITE") { } elsif ($hash->{DBMODEL} eq "SQLITE") {
$sqlspec{get_timestamp} = "TIMESTAMP"; $sqlspec{get_timestamp} = "TIMESTAMP";
$sqlspec{from_timestamp} = "'$from'"; $sqlspec{from_timestamp} = "'$from'";
$sqlspec{to_timestamp} = "'$to'"; $sqlspec{to_timestamp} = "'$to'";
$sqlspec{reading_clause} = "(DEVICE || '|' || READING)";
} else { } else {
$sqlspec{get_timestamp} = "TIMESTAMP"; $sqlspec{get_timestamp} = "TIMESTAMP";
$sqlspec{from_timestamp} = "'$from'"; $sqlspec{from_timestamp} = "'$from'";
$sqlspec{to_timestamp} = "'$to'"; $sqlspec{to_timestamp} = "'$to'";
$sqlspec{reading_clause} = "(DEVICE || '|' || READING)";
} }
if(uc($outf) eq "ALL") { if(uc($outf) eq "ALL") {
@ -571,14 +643,11 @@ DbLog_Get($@)
my $stm= "SELECT my $stm= "SELECT
$sqlspec{get_timestamp}, $sqlspec{get_timestamp},
DEVICE,
READING,
VALUE VALUE
$sqlspec{all} $sqlspec{all}
FROM history FROM history
WHERE 1=1 WHERE
AND $sqlspec{reading_clause} = ('".$readings[$i]->[0]."|".$readings[$i]->[1]."') DEVICE = '".$readings[$i]->[0]."'
AND DEVICE = '".$readings[$i]->[0]."'
AND READING = '".$readings[$i]->[1]."' AND READING = '".$readings[$i]->[1]."'
AND TIMESTAMP > $sqlspec{from_timestamp} AND TIMESTAMP > $sqlspec{from_timestamp}
AND TIMESTAMP < $sqlspec{to_timestamp} AND TIMESTAMP < $sqlspec{to_timestamp}
@ -592,10 +661,16 @@ DbLog_Get($@)
return "Cannot execute statement $stm: $DBI::errstr"; return "Cannot execute statement $stm: $DBI::errstr";
if(uc($outf) eq "ALL") { 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 .= "Timestamp: Device, Type, Event, Reading, Value, Unit\n";
$retval .= "=====================================================\n"; $retval .= "=====================================================\n";
} }
while( ($sql_timestamp,$sql_dev,$sql_reading,$sql_value, $type, $event, $unit)= $sth->fetchrow_array) { else {
$sth->bind_columns(undef, \$sql_timestamp, \$sql_value);
}
while($sth->fetch()) {
$writeout = 0; $writeout = 0;
$out_value = ""; $out_value = "";
$out_tstamp = ""; $out_tstamp = "";
@ -606,7 +681,7 @@ DbLog_Get($@)
my $val = $sql_value; my $val = $sql_value;
eval("$readings[$i]->[4]"); eval("$readings[$i]->[4]");
$sql_value = $val; $sql_value = $val;
if($@) {Log 3, "DbLog: Error in inline function: <".$readings[$i]->[4].">, Fehler: $@";} if($@) {Log 3, "DbLog: Error in inline function: <".$readings[$i]->[4].">, Error: $@";}
$out_tstamp = $sql_timestamp; $out_tstamp = $sql_timestamp;
$writeout=1; $writeout=1;
} }
@ -665,14 +740,14 @@ DbLog_Get($@)
###################### Ausgabe ########################### ###################### Ausgabe ###########################
if($writeout) { if($writeout) {
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, $readings[$i]->[0], $type, $event, $readings[$i]->[1], $out_value, $unit);
} else { } else {
$out_tstamp =~ s/\ /_/g; #needed by generating plots $out_tstamp =~ s/\ /_/g; #needed by generating plots
$retval .= "$out_tstamp $out_value\n"; $retval .= "$out_tstamp $out_value\n";
} }
} }
if(defined($sql_value) || $sql_value =~ m/^[-\.\d]+$/o){ if(Scalar::Util::looks_like_number($sql_value)){
#nur setzen wenn nummerisch #nur setzen wenn nummerisch
$min[$i] = $sql_value if($sql_value < $min[$i]); $min[$i] = $sql_value if($sql_value < $min[$i]);
$max[$i] = $sql_value if($sql_value > $max[$i]);; $max[$i] = $sql_value if($sql_value > $max[$i]);;
@ -698,7 +773,7 @@ DbLog_Get($@)
$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, $readings[$i]->[0], $type, $event, $readings[$i]->[1], $out_value, $unit);
} else { } else {
$out_tstamp =~ s/\ /_/g; #needed by generating plots $out_tstamp =~ s/\ /_/g; #needed by generating plots
$retval .= "$out_tstamp $out_value\n"; $retval .= "$out_tstamp $out_value\n";
@ -759,7 +834,7 @@ sub jsonError($) {
# Prepare the SQL String # Prepare the SQL String
# #
################################################################ ################################################################
sub prepareSql(@_) { sub prepareSql(@) {
my ($hash, @a) = @_; my ($hash, @a) = @_;
my $starttime = $_[5]; my $starttime = $_[5];

File diff suppressed because it is too large Load Diff