Neues Modul 98_FileLogConvert.pm - FileLog Import in DbLog und mehr

Begonnen von DeeSPe, 04 Februar 2017, 12:20:07

Vorheriges Thema - Nächstes Thema

JimKnopf

Hi!

Dann muss ich mir ja nicht nur Gedanken über das Einlesen der Logdatei machen, sondern mich auch wieder mit SQL in c++ beschäftigen.
Ich guck mir das Perl Modul mal an, vielleicht kapiere ich ja wie das aufgebaut ist, dann bau ich das da direkt ein.

Gruß,
Burkhard
FHEM,LaCrosse,PCA301,Revolt,MAX!,HM,FS20, MQTT2, ebusd 3.4.v3.4-96-g96d5623, ebus Adapter 3.0 mit 20201219-offset , Wolf  CGB (-K)-20, Wolf ISM7, Wolf Solar SM, Speicher/WR E3DC S10, eGolf, Keba P30, Phoenix Contact EV, OpenWB

Otto123

Ne guck Dir lieber mein SQL Script (#80) an, dass ist einfacher. Aber ja vielleicht hast Du recht, mach einfach andere Logs :)
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

JimKnopf

#92
So Leute,
ich hab mich mal ein wenig mit Perl beschäftigt und die Funktion zum konvertieren abgeändert wie folgt:
1. Ein paar Variablen hinzugefügt (Reading 2 - 5, Value 2-5, event 2-5)
2. einen Abschnitt, wo die Logline analysiert wird, wie viele Elemente enthalten sind, 4 mal kopiert und abgeändert, so das zusätzlich auf 2 bis 5 reading: value Pärchen geprüft wird
3. wurden in den neuen Abschnitten weitere Werte in der Zeile erkannt, wird für diese nochmals ein Datensatz mit diesen Werten in die Datenbank geschrieben.

hier die vollständige Subroutine mit den Änderungen (mit # Komentaren):

sub FileLogConvert_FileRead($)
{
#noch original, erste Änderunge weiter unten
  my ($string) = @_;
  return unless (defined $string);
  my @a       = split /\|/,$string;
  my $name    = $a[0];
  my $hash    = $defs{$name};
  my $cmd     = $hash->{helper}{filedata}{cmd};
  my $dir     = $hash->{helper}{filedata}{dir};
  my $source  = $hash->{helper}{filedata}{source};
  my $dblog   = $hash->{helper}{filedata}{dblog};
  my $eventregex = $hash->{helper}{filedata}{eventregex} ? $hash->{helper}{filedata}{eventregex} : ".*";
  my $stateregex = $hash->{helper}{filedata}{stateregex} ? $hash->{helper}{filedata}{stateregex} : ".*";
  $stateregex =~ s/:/|/g;
  delete $hash->{helper}{filedata};
  my $fname   = "$dir/$source";
  my @events;
  if (!open FH,$fname)
  {
    close(FH);
    my $err = encode_base64("could not read $fname","");
    return "$name|''|$err";
  }
  my $arows = 0;
  my $crows = 0;
  my $dest = $source;
  $dest =~ s/log$/csv/ if ($cmd eq "convert2csv");
  $dest =~ s/log$/sql/ if ($cmd eq "convert2sql");
  $dest =~ s/log$/$dblog/ if ($cmd eq "import2DbLog");
  if ($cmd =~ /^(convert2(csv|sql)|import2DbLog)$/)
  {
    if (!open WH,">>$dir/$dest")
    {
      close WH;
      my $err = encode_base64("could not write $dir/$dest","");
      return "$name|''|$err";
    }
  }
  while (my $line = <FH>)
  {
    $arows++;
    chomp $line;
    $line =~ s/\s{2,}/ /g;
    if ($cmd eq "fileEvents")
    {
      next unless ($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s([A-Za-z0-9\.\-_]+):\s(\S+)(\s.*)?$/
        || $line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s([A-Za-z0-9\.\-_]+)$/);
      push @events,$4 if (!grep(/^$4$/,@events));
    }
    else
    {
      my $i_date;
      my $i_time;
      my $i_device;
      my $i_type;
      my $i_event;
      my $i_reading;
      my $i_value;
#hier die ersten Änderungen
     my $i_reading2;
      my $i_value2;
      my $i_reading3;
      my $i_value3;
      my $i_reading4;
      my $i_value4;
      my $i_reading5;
      my $i_value5;
      my $i_unit = ""; # diese Zeile ist noch orignial
      $i_reading2=undef; #bei jedem Durchlauf zurücksetzen um prüfen zu können ob sie genutzt wurden
      $i_reading3=undef;
      $i_reading4=undef;
      $i_reading5=undef;
      $i_value2=undef;
      $i_value3=undef;
      $i_value4=undef;
      $i_value5=undef;
     
#Abfrage der Logstruktur erweitert um 4 x \s([A-Za-z0-9\.\-_]+):\s(\S+)(\s.*)
      if    ($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)(\s.*)?$/)
      {
        $i_date = $1;
        $i_time = $2;
        $i_device = $3;
        $i_reading = $4;
        $i_value = $5;
        $i_reading2 = $6;
        $i_value2 = $7;
        $i_reading3 = $8;
        $i_value3 = $9;
        $i_reading4 = $10;
        $i_value4 = $11;
        $i_reading5 = $12;
        $i_value5 = $13;
my $rest = $12 if ($12);
       
        $i_type = IsDevice($i_device) ? uc $defs{$i_device}->{TYPE} : "";
        $i_event = "$i_reading: $i_value";
        $i_event .= " $rest" if ($rest);
        $i_event2 = "$i_reading: $i_value";
        $i_event2 .= " $rest" if ($rest);
        $i_event3 = "$i_reading: $i_value";
        $i_event3 .= " $rest" if ($rest);
        $i_event4 = "$i_reading: $i_value";
        $i_event4 .= " $rest" if ($rest);
        $i_event5 = "$i_reading: $i_value";
        $i_event5 .= " $rest" if ($rest);
      }
      elsif    ($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)(\s.*)?$/)
      {
        $i_date = $1;
        $i_time = $2;
        $i_device = $3;
        $i_reading = $4;
        $i_value = $5;
        $i_reading2 = $6;
        $i_value2 = $7;
        $i_reading3 = $8;
        $i_value3 = $9;
        $i_reading4 = $10;
        $i_value4 = $11;
        my $rest = $12 if ($12);
        $i_type = IsDevice($i_device) ? uc $defs{$i_device}->{TYPE} : "";
        $i_event = "$i_reading: $i_value";
        $i_event .= " $rest" if ($rest);
        $i_event2 = "$i_reading: $i_value";
        $i_event2 .= " $rest" if ($rest);
        $i_event3 = "$i_reading: $i_value";
        $i_event3 .= " $rest" if ($rest);
        $i_event4 = "$i_reading: $i_value";
        $i_event4 .= " $rest" if ($rest);
      }
      elsif    ($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)(\s.*)?$/)
      {
        $i_date = $1;
        $i_time = $2;
        $i_device = $3;
        $i_reading = $4;
        $i_value = $5;
        $i_reading2 = $6;
        $i_value2 = $7;
        $i_reading3 = $8;
        $i_value3 = $9;
        my $rest = $10 if ($10);
        $i_type = IsDevice($i_device) ? uc $defs{$i_device}->{TYPE} : "";
        $i_event = "$i_reading: $i_value";
        $i_event .= " $rest" if ($rest);
        $i_event2 = "$i_reading: $i_value";
        $i_event2 .= " $rest" if ($rest);
        $i_event3 = "$i_reading: $i_value";
        $i_event3 .= " $rest" if ($rest);
      }
      elsif    ($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)(\s.*)?$/)
      {
        $i_date = $1;
        $i_time = $2;
        $i_device = $3;
        $i_reading = $4;
        $i_value = $5;
        $i_reading2 = $6;
        $i_value2 = $7;
        my $rest = $8 if ($8);
        $i_type = IsDevice($i_device) ? uc $defs{$i_device}->{TYPE} : "";
        $i_event = "$i_reading: $i_value";
        $i_event .= " $rest" if ($rest);
        $i_event2 = "$i_reading: $i_value";
        $i_event2 .= " $rest" if ($rest);
      }
      elsif    ($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s+([A-Za-z0-9\.\-_]+):\s+(\S+)(\s.*)?$/)
      {
        $i_date = $1;
        $i_time = $2;
        $i_device = $3;
        $i_reading = $4;
        $i_value = $5;
        my $rest = $6 if ($6);
        $i_type = IsDevice($i_device) ? uc $defs{$i_device}->{TYPE} : "";
        $i_event = "$i_reading: $i_value";
        $i_event .= " $rest" if ($rest);
      }
     
     
# ab hier erst mal wieder original weiter     
     
      elsif ($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s([A-Za-z0-9\.\-_]+):\s(\S+)(\s.*)?$/)
      {
        $i_date = $1;
        $i_time = $2;
        $i_device = $3;
        $i_reading = $4;
        $i_value = $5;
        my $rest = $6 if ($6);
        next if ($i_reading !~ /^($eventregex)$/);
        $i_unit = $rest ? (split " ",$rest)[0] : "";
        $i_unit = "" if ($i_unit =~ /^[\/\[\{\(]/);
        $i_type = IsDevice($i_device) ? uc $defs{$i_device}->{TYPE} : "";
        $i_event = "$i_reading: $i_value";
        $i_event .= " $rest" if ($rest);
      }
      elsif ($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s([A-Za-z0-9\.\-_]+)$/)
      {
        $i_date = $1;
        $i_time = $2;
        $i_device = $3;
        $i_value = $4;
        next if ($i_value !~ /^($eventregex)$/);
        $i_type = IsDevice($i_device) ? uc $defs{$i_device}->{TYPE} : "";
        $i_reading = "state";
        $i_event = $i_value;
      }
      else
      {
        next;
      }
      $crows++;
      my $ret;
     
 
      { # in Klammern gesetzt zur besseren lesbarkeit, der Code in dieser Klammer ist original
$ret = "INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES ('$i_date $i_time','$i_device','$i_type','$i_event','$i_reading','$i_value','$i_unit');" if ($cmd =~ /^(import2DbLog|convert2sql)$/);
$ret = '"'.$i_date.' '.$i_time.'","'.$i_device.'","'.$i_type.'","'.$i_event.'","'.$i_reading.'","'.$i_value.'","'.$i_unit.'"' if ($cmd eq "convert2csv");
DbLog_ExecSQL($defs{$dblog},$ret) if ($cmd eq "import2DbLog");
print WH $ret,"\n" if ($cmd =~ /^convert2(csv|sql)$/);
  }
# jetzt prüfen ob weitere readings gefunden wurden
  if (defined $i_reading2)# hatten wir ja zu Beginn auf undef gesetzt, wurde sie neu beschrieben? Dann die SQL Funktion mit reading2/value2 ausführen
      {
$ret = "INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES ('$i_date $i_time','$i_device','$i_type','$i_event','$i_reading2','$i_value2','$i_unit');" if ($cmd =~ /^(import2DbLog|convert2sql)$/);
$ret = '"'.$i_date.' '.$i_time.'","'.$i_device.'","'.$i_type.'","'.$i_event.'","'.$i_reading2.'","'.$i_value2.'","'.$i_unit.'"' if ($cmd eq "convert2csv");
DbLog_ExecSQL($defs{$dblog},$ret) if ($cmd eq "import2DbLog");
print WH $ret,"\n" if ($cmd =~ /^convert2(csv|sql)$/);
  }
  if (defined $i_reading3)# usw.
      {
$ret = "INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES ('$i_date $i_time','$i_device','$i_type','$i_event','$i_reading3','$i_value3','$i_unit');" if ($cmd =~ /^(import2DbLog|convert2sql)$/);
$ret = '"'.$i_date.' '.$i_time.'","'.$i_device.'","'.$i_type.'","'.$i_event.'","'.$i_reading3.'","'.$i_value3.'","'.$i_unit.'"' if ($cmd eq "convert2csv");
DbLog_ExecSQL($defs{$dblog},$ret) if ($cmd eq "import2DbLog");
print WH $ret,"\n" if ($cmd =~ /^convert2(csv|sql)$/);
  }
  if (defined $i_reading4)
      {
$ret = "INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES ('$i_date $i_time','$i_device','$i_type','$i_event','$i_reading4','$i_value4','$i_unit');" if ($cmd =~ /^(import2DbLog|convert2sql)$/);
$ret = '"'.$i_date.' '.$i_time.'","'.$i_device.'","'.$i_type.'","'.$i_event.'","'.$i_reading4.'","'.$i_value4.'","'.$i_unit.'"' if ($cmd eq "convert2csv");
DbLog_ExecSQL($defs{$dblog},$ret) if ($cmd eq "import2DbLog");
print WH $ret,"\n" if ($cmd =~ /^convert2(csv|sql)$/);
  }
  if (defined $i_reading5)
      {
$ret = "INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES ('$i_date $i_time','$i_device','$i_type','$i_event','$i_reading5','$i_value5','$i_unit');" if ($cmd =~ /^(import2DbLog|convert2sql)$/);
$ret = '"'.$i_date.' '.$i_time.'","'.$i_device.'","'.$i_type.'","'.$i_event.'","'.$i_reading5.'","'.$i_value5.'","'.$i_unit.'"' if ($cmd eq "convert2csv");
DbLog_ExecSQL($defs{$dblog},$ret) if ($cmd eq "import2DbLog");
print WH $ret,"\n" if ($cmd =~ /^convert2(csv|sql)$/);
  }
#ab hier wieder original
    }
  }
  close WH if ($cmd =~ /^(convert2(csv|sql)|import2DbLog)$/);
  close FH;
  my $events = @events ? encode_base64(join(" ",@events),"") : "";
  my $regex = $eventregex ? encode_base64($eventregex,"") : "";
  return "$name|$cmd,$source,$arows,$dest,$crows,$events,$regex";
}


Ich prüfe erst auf das 5. reading:value Pärchen, dann 4.,3.,2.,1. weil 4 ja in 5 enthalten wäre usw.. Ich habe die Leerstellentoleranz erhöt, es dürfen auch mehr als eine zwischen den Werten sein.
Danach wird dann das Original mit my $rest ausgeführt.


Das Ergebnis im logdb:
Date             Time              Device                       Type        Event        Reading   Value
2020-03-27 04:25:06    EM_Kuehlschrank    CUL_EM    CNT: 88    CNT            88    
2020-03-27 04:25:06    EM_Kuehlschrank    CUL_EM    CNT: 88    CUM    79.815    
2020-03-27 04:25:06    EM_Kuehlschrank    CUL_EM    CNT: 88    5MIN    0.080    
2020-03-27 04:25:06    EM_Kuehlschrank    CUL_EM    CNT: 88    TOP            0.080    

Für mich funktioniert das jetzt.
Gruß,
Burkhard
FHEM,LaCrosse,PCA301,Revolt,MAX!,HM,FS20, MQTT2, ebusd 3.4.v3.4-96-g96d5623, ebus Adapter 3.0 mit 20201219-offset , Wolf  CGB (-K)-20, Wolf ISM7, Wolf Solar SM, Speicher/WR E3DC S10, eGolf, Keba P30, Phoenix Contact EV, OpenWB

Speedy

Zitat von: DeeSPe am 01 November 2019, 09:30:02
Hallo ddw,

das ist ja interessant, könntest Du mir bitte die komplette geänderte Moduldatei von Dir zukommen lassen?

Danke.

Gruß
Dan

Hallo Dan,

ich weiss, das ist schon ein paar Tage her... - ich wollte aber trotzdem mal fragen, ob Du Dir den Vorschlag von ddw mal angeschaut hattest. Ich möchte derzeit auch eine Menge an Logfiles in meine MariaDB mittels Deines Tools importieren. Allerdings ist es auch bei mir so langsam, dass das Vorgehen so nicht praktikabel ist.

Oder gibt es noch andere Möglichkeiten den Import zu beschleunigen?

Danke und viele Grüße


- Speedy
FHEM auf Intel NUC mit Proxmox, Grafana, DbLog mit MariaDB, ZWave-/EnOcean-/HomeMatic-USB-Dongle, KNX IP-Bridge, HUE Bridge, Sonos, Avanta Gastherme, Presence via Unifi, Rolladensteuerung, Raumtemperatur-/Fussbodenheizung-Steuerung