2007-12-30 21:51:16 +00:00
|
|
|
##############################################
|
|
|
|
#
|
|
|
|
# 93_DbLog.pm
|
|
|
|
# written by Dr. Boris Neubert 2007-12-30
|
|
|
|
# e-mail: omega at online dot de
|
|
|
|
#
|
|
|
|
##############################################
|
|
|
|
|
|
|
|
package main;
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use DBI;
|
|
|
|
|
|
|
|
sub DbLog($$$);
|
|
|
|
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
sub
|
|
|
|
DbLog_Initialize($)
|
|
|
|
{
|
|
|
|
my ($hash) = @_;
|
|
|
|
|
|
|
|
$hash->{DefFn} = "DbLog_Define";
|
|
|
|
$hash->{UndefFn} = "DbLog_Undef";
|
|
|
|
$hash->{NotifyFn} = "DbLog_Log";
|
|
|
|
$hash->{AttrFn} = "DbLog_Attr";
|
|
|
|
$hash->{AttrList} = "disable:0,1";
|
|
|
|
}
|
|
|
|
|
|
|
|
#####################################
|
|
|
|
sub
|
|
|
|
DbLog_Define($@)
|
|
|
|
{
|
|
|
|
my ($hash, $def) = @_;
|
|
|
|
my @a = split("[ \t][ \t]*", $def);
|
|
|
|
|
2008-11-02 18:04:33 +00:00
|
|
|
return "wrong syntax: define <name> DbLog configuration regexp"
|
2007-12-30 21:51:16 +00:00
|
|
|
if(int(@a) != 4);
|
|
|
|
|
|
|
|
my $regexp = $a[3];
|
|
|
|
|
|
|
|
eval { "Hallo" =~ m/^$regexp$/ };
|
|
|
|
return "Bad regexp: $@" if($@);
|
|
|
|
$hash->{REGEXP} = $regexp;
|
|
|
|
|
|
|
|
$hash->{configuration}= $a[2];
|
|
|
|
|
|
|
|
return "Can't connect to database." if(!DbLog_Connect($hash));
|
|
|
|
|
|
|
|
$hash->{STATE} = "active";
|
|
|
|
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
|
|
|
#####################################
|
|
|
|
sub
|
|
|
|
DbLog_Undef($$)
|
|
|
|
{
|
|
|
|
my ($hash, $name) = @_;
|
|
|
|
my $dbh= $hash->{DBH};
|
2008-11-02 18:04:33 +00:00
|
|
|
$dbh->disconnect() if(defined($dbh));
|
2007-12-30 21:51:16 +00:00
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
sub
|
|
|
|
DbLog_Attr(@)
|
|
|
|
{
|
|
|
|
my @a = @_;
|
|
|
|
my $do = 0;
|
|
|
|
|
|
|
|
if($a[0] eq "set" && $a[2] eq "disable") {
|
|
|
|
$do = (!defined($a[3]) || $a[3]) ? 1 : 2;
|
|
|
|
}
|
|
|
|
$do = 2 if($a[0] eq "del" && (!$a[2] || $a[2] eq "disable"));
|
|
|
|
return if(!$do);
|
|
|
|
|
|
|
|
$defs{$a[1]}{STATE} = ($do == 1 ? "disabled" : "active");
|
|
|
|
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
sub
|
|
|
|
DbLog_ParseEvent($$)
|
|
|
|
{
|
|
|
|
my ($type, $event)= @_;
|
|
|
|
my @result;
|
|
|
|
|
|
|
|
# split the event into reading and argument
|
|
|
|
# "day-temp: 22.0 (Celsius)" -> "day-temp", "22.0 (Celsius)"
|
|
|
|
my @parts= split(/: /,$event);
|
|
|
|
my $reading= $parts[0]; if(!defined($reading)) { $reading= ""; }
|
|
|
|
my $arg= $parts[1];
|
|
|
|
|
|
|
|
# the interpretation of the argument depends on the device type
|
|
|
|
|
|
|
|
#default
|
|
|
|
my $value= $arg; if(!defined($value)) { $value= ""; }
|
|
|
|
my $unit= "";
|
|
|
|
|
|
|
|
|
|
|
|
# EMEM, M232Counter, M232Voltage return plain numbers
|
2008-11-02 18:04:33 +00:00
|
|
|
if(($type eq "M232Voltage") ||
|
2007-12-30 21:51:16 +00:00
|
|
|
($type eq "M232Counter") ||
|
|
|
|
($type eq "EMEM")) {
|
|
|
|
}
|
2008-01-06 12:50:25 +00:00
|
|
|
# FS20
|
2008-11-02 18:04:33 +00:00
|
|
|
elsif(($type eq "FS20") ||
|
|
|
|
($type eq "X10")) {
|
2008-01-06 12:50:25 +00:00
|
|
|
@parts= split(/ /,$value);
|
|
|
|
my $reading= $parts[0]; if(!defined($reading)) { $reading= ""; }
|
2008-03-24 21:37:20 +00:00
|
|
|
if($#parts>=1) {
|
|
|
|
$value= join(" ", shift @parts);
|
2008-11-02 18:04:33 +00:00
|
|
|
if($reading =~ m(^dim*%$)) {
|
2008-03-24 21:37:20 +00:00
|
|
|
$value= substr($reading,3,length($reading)-4);
|
|
|
|
$reading= "dim";
|
|
|
|
$unit= "%";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$value= "";
|
|
|
|
}
|
2008-01-06 12:50:25 +00:00
|
|
|
}
|
|
|
|
}
|
2008-11-02 18:04:33 +00:00
|
|
|
# FHT
|
2007-12-30 21:51:16 +00:00
|
|
|
elsif($type eq "FHT") {
|
2008-05-02 14:05:41 +00:00
|
|
|
if($reading =~ m(-from[12]\ ) || $reading =~ m(-to[12]\ )) {
|
|
|
|
@parts= split(/ /,$event);
|
|
|
|
$reading= $parts[0];
|
|
|
|
$value= $parts[1];
|
|
|
|
$unit= "";
|
|
|
|
}
|
2007-12-30 21:51:16 +00:00
|
|
|
if($reading =~ m(-temp)) { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
|
|
|
|
if($reading =~ m(temp-offset)) { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
|
2008-11-02 18:04:33 +00:00
|
|
|
if($reading =~ m(^actuator[0-9]*)) {
|
2008-03-25 17:54:14 +00:00
|
|
|
if($value eq "lime-protection") {
|
|
|
|
$reading= "actuator-lime-protection";
|
|
|
|
undef $value;
|
|
|
|
}
|
2008-05-02 14:05:41 +00:00
|
|
|
elsif($value =~ m(^offset:)) {
|
|
|
|
$reading= "actuator-offset";
|
|
|
|
@parts= split(/: /,$value);
|
|
|
|
$value= $parts[1];
|
|
|
|
if(defined $value) {
|
|
|
|
$value=~ s/%//; $value= $value*1.; $unit= "%";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elsif($value =~ m(^unknown_)) {
|
|
|
|
@parts= split(/: /,$value);
|
|
|
|
$reading= "actuator-" . $parts[0];
|
|
|
|
$value= $parts[1];
|
|
|
|
if(defined $value) {
|
|
|
|
$value=~ s/%//; $value= $value*1.; $unit= "%";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elsif($value eq "synctime") {
|
|
|
|
$reading= "actuator-synctime";
|
|
|
|
undef $value;
|
|
|
|
}
|
|
|
|
elsif($value eq "test") {
|
|
|
|
$reading= "actuator-test";
|
|
|
|
undef $value;
|
|
|
|
}
|
|
|
|
elsif($value eq "pair") {
|
|
|
|
$reading= "actuator-pair";
|
|
|
|
undef $value;
|
|
|
|
}
|
2008-03-25 17:54:14 +00:00
|
|
|
else {
|
2008-11-02 18:04:33 +00:00
|
|
|
$value=~ s/%//; $value= $value*1.; $unit= "%";
|
2008-03-25 17:54:14 +00:00
|
|
|
}
|
2008-03-24 21:37:20 +00:00
|
|
|
}
|
2007-12-30 21:51:16 +00:00
|
|
|
}
|
|
|
|
# KS300
|
|
|
|
elsif($type eq "KS300") {
|
|
|
|
if($event =~ m(T:.*)) { $reading= "data"; $value= $event; }
|
|
|
|
if($event =~ m(avg_day)) { $reading= "data"; $value= $event; }
|
|
|
|
if($event =~ m(avg_month)) { $reading= "data"; $value= $event; }
|
|
|
|
if($reading eq "temperature") { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
|
|
|
|
if($reading eq "wind") { $value=~ s/ \(km\/h\)//; $unit= "km/h"; }
|
|
|
|
if($reading eq "rain") { $value=~ s/ \(l\/m2\)//; $unit= "l/m2"; }
|
|
|
|
if($reading eq "rain_raw") { $value=~ s/ \(counter\)//; $unit= ""; }
|
|
|
|
if($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; }
|
2008-11-02 18:04:33 +00:00
|
|
|
if($reading eq "israining") {
|
|
|
|
$value=~ s/ \(yes\/no\)//;
|
2007-12-30 21:51:16 +00:00
|
|
|
$value=~ s/no/0/;
|
|
|
|
$value=~ s/yes/1/;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# HMS
|
|
|
|
elsif($type eq "HMS") {
|
|
|
|
if($event =~ m(T:.*)) { $reading= "data"; $value= $event; }
|
|
|
|
if($reading eq "temperature") { $value=~ s/ \(Celsius\)//; $unit= "°C"; }
|
|
|
|
if($reading eq "humidity") { $value=~ s/ \(\%\)//; $unit= "%"; }
|
2008-11-02 18:04:33 +00:00
|
|
|
if($reading eq "battery") {
|
2007-12-30 21:51:16 +00:00
|
|
|
$value=~ s/ok/1/;
|
|
|
|
$value=~ s/replaced/1/;
|
|
|
|
$value=~ s/empty/0/;
|
|
|
|
}
|
|
|
|
}
|
2008-11-02 18:04:33 +00:00
|
|
|
|
2007-12-30 21:51:16 +00:00
|
|
|
|
|
|
|
@result= ($reading,$value,$unit);
|
|
|
|
return @result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
sub
|
|
|
|
DbLog_Log($$)
|
|
|
|
{
|
|
|
|
# Log is my entry, Dev is the entry of the changed device
|
|
|
|
my ($log, $dev) = @_;
|
2008-11-02 18:04:33 +00:00
|
|
|
|
2007-12-30 21:51:16 +00:00
|
|
|
# name and type required for parsing
|
|
|
|
my $n= $dev->{NAME};
|
|
|
|
my $t= $dev->{TYPE};
|
|
|
|
|
|
|
|
# timestamp in SQL format YYYY-MM-DD hh:mm:ss
|
|
|
|
#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 $max = int(@{$dev->{CHANGED}});
|
|
|
|
for (my $i = 0; $i < $max; $i++) {
|
|
|
|
my $s = $dev->{CHANGED}[$i];
|
|
|
|
$s = "" if(!defined($s));
|
|
|
|
if($n =~ m/^$re$/ || "$n:$s" =~ m/^$re$/) {
|
|
|
|
my $ts = TimeNow();
|
|
|
|
$ts = $dev->{CHANGETIME}[$i] if(defined($dev->{CHANGETIME}[$i]));
|
|
|
|
# $ts is in SQL format YYYY-MM-DD hh:mm:ss
|
|
|
|
|
|
|
|
my @r= DbLog_ParseEvent($t, $s);
|
|
|
|
my $reading= $r[0];
|
|
|
|
my $value= $r[1];
|
|
|
|
my $unit= $r[2];
|
2008-11-02 18:04:33 +00:00
|
|
|
if(!defined $reading) { $reading= ""; }
|
|
|
|
if(!defined $value) { $value= ""; }
|
|
|
|
if(!defined $unit) { $unit= ""; }
|
|
|
|
|
2007-12-30 21:51:16 +00:00
|
|
|
|
|
|
|
my $is= "(TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES " .
|
|
|
|
"('$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);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
sub
|
|
|
|
DbLog_Connect($)
|
|
|
|
{
|
|
|
|
my ($hash)= @_;
|
|
|
|
|
|
|
|
my $configfilename= $hash->{configuration};
|
|
|
|
if(!open(CONFIG, $configfilename)) {
|
|
|
|
Log 1, "Cannot open database configuration file $configfilename.";
|
|
|
|
return 0; }
|
|
|
|
my @config=<CONFIG>;
|
|
|
|
close(CONFIG);
|
|
|
|
|
|
|
|
my %dbconfig;
|
|
|
|
eval join("", @config);
|
|
|
|
|
|
|
|
my $dbconn= $dbconfig{connection};
|
|
|
|
my $dbuser= $dbconfig{user};
|
|
|
|
my $dbpassword= $dbconfig{password};
|
|
|
|
|
|
|
|
Log 3, "Connecting to database $dbconn with user $dbuser";
|
|
|
|
my $dbh = DBI->connect_cached("dbi:$dbconn", $dbuser, $dbpassword);
|
|
|
|
if(!$dbh) {
|
|
|
|
Log 1, "Can't connect to $dbconn: $DBI::errstr";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
Log 3, "Connection to db $dbconn established";
|
|
|
|
$hash->{DBH}= $dbh;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
sub
|
|
|
|
DbLog_ExecSQL1($$)
|
|
|
|
{
|
|
|
|
my ($dbh,$sql)= @_;
|
2008-11-02 18:04:33 +00:00
|
|
|
|
2007-12-30 21:51:16 +00:00
|
|
|
my $sth = $dbh->do($sql);
|
|
|
|
if(!$sth) {
|
|
|
|
Log 2, "DBLog error: " . $DBI::errstr;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub
|
|
|
|
DbLog_ExecSQL($$)
|
|
|
|
{
|
|
|
|
my ($hash,$sql)= @_;
|
2008-11-02 18:04:33 +00:00
|
|
|
|
2007-12-30 21:51:16 +00:00
|
|
|
Log 5, "Executing $sql";
|
|
|
|
my $dbh= $hash->{DBH};
|
|
|
|
if(!DbLog_ExecSQL1($dbh,$sql)) {
|
|
|
|
#retry
|
|
|
|
$dbh->disconnect();
|
|
|
|
if(!DbLog_Connect($hash)) {
|
|
|
|
Log 2, "DBLog reconnect failed.";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
$dbh= $hash->{DBH};
|
|
|
|
if(!DbLog_ExecSQL1($dbh,$sql)) {
|
|
|
|
Log 2, "DBLog retry failed.";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
Log 2, "DBLog retry ok.";
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
1;
|