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

DeeSPe

Zitat von: Tueftler1983 am 23 Juni 2019, 15:13:19
Hallo, habe alle Log's auf der SSD unter /media/ssd/log/
Allerdings wenn ich in dem device die logdir angeben will kommt immer die Meldung das das Verzeichnis nicht existiert.

Was kann ich tun

Ich zitiere mal aus der commandref:
Zitatlogdir
must be a valid (relative) subfolder of "./fhem/"
relative paths are also possible to address paths outside "./fhem/", e.g. "../../home/pi/oldlogs"

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Tueftler1983

Okay danke, hatte es auch schon versucht klappte aber am Anfang nicht mit dem ../../

Habe es dann nochmal versucht und jetzt geht es.
Danke

Otto123

#77
Hi,

ich bin auf der Suche nach einem Fehlerfreiem Import von bisherigen LogFiles, deren Einträge so aussehen:
2018-12-31_23:56:15 SensorAussen T: 7.3 H: 90 D: 5.8
Der Eintrag der durch Import in der LogDb entsteht sieht dann so aus:
+---------------------+--------------+-------+-------------------------------+---------+--------------+------+
| TIMESTAMP           | DEVICE       | TYPE  | EVENT                         | READING | VALUE        | UNIT |
+---------------------+--------------+-------+-------------------------------+---------+--------------+------+
| 2018-12-31 23:56:15 | SensorAussen |       | T: 7.3 H: 90 D: 5.8           | T       | 7.3          | H:   |

Das ist nicht das was ich wollte. Nach einigen eigenen "Erkenntnissen" war klar: stateEvent fehlt.
Mein erster Versuch war diesen in die alten Logs einfach einzufügen:
sed 's/Aussen.T:/Aussen state T:/'Das funktioniert nicht sofort wie es sollte.  :'(

Da habe ich etwas weiter ausgeholt:
- FileLog um addStateEvent erweitert.
- LogDb und FilelLog haben jetzt einheitliches regExp: SensorAussen:.*
Nun habe ich neue "Referenzwerte" und weiß wie ich die alten Logs modifizieren muss. (Dachte ich)  ;)
Die Einträge sehen nun so aus:
Eintrag FileLog
2019-08-19_13:12:35 SensorAussen state: T: 23.1 H: 54

Eintrag DBLog
2019-08-19 13:12:35 | SensorAussen | DUMMY | state: T: 23.1 H: 54 | state       | T: 23.1 H: 54 |      |

Jetzt geh ich her und exportiere diese Zeile aus dem neuen FileLog in ein neues LogFile, modifiziere die Sekunde um eins und importiere anschließend diese eine Zeile wieder in die LogDB
cat /opt/fhem/log/SensorAussen-2019.log |grep -a "2019-08-19_13:12:35"|sed 's/:35/:36/'> /opt/fhem/log/SensorAussen-2019-1.log
Der Eintrag sieht dann so aus. Oben der Originale unten der importierte aus dem FileLog:
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+
| TIMESTAMP           | DEVICE       | TYPE  | EVENT                 | READING     | VALUE         | UNIT |
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+
| 2019-08-19 13:12:35 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T: 23.1 H: 54 |      |
| 2019-08-19 13:12:36 | SensorAussen | DUMMY | state: T:  23.1 H: 54 | state       | T:            | 23.1 |
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+

Wie man sieht wird ein Leerzeichen zwischen T: und 23.1 reingemogelt, welches offenbar zu dem fehlerhaften Import führt.
Für mich fällt mir jetzt keine Lösung ein, denn auch die Beseitigung des ursprünglichen Leerzeichens führt (fast erwartungsgemäß) nicht zum Erfolg: Aus "state: T:23.1 H: 54" wird dann "state: T:23.1  H: 54" also auch wieder ein Leerzeichen mehr drin, bloß weiter hinten :)

Hat jemand eine Idee?

Edit: Das Leerzeichen kommt aus Zeile 246 " $rest"
        $i_event .= " $rest" if ($rest);

Allerdings verhindert dort eine Änderung allein nicht die Aufteilung des Value
| 2019-08-19 13:12:39 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T:            | 23.1 |
Edit2:Das regExp in Zeile 233 nimmt nicht einfach alles nach dem ReadingName (state) als Value (wie es eigentlich geloggt wird ) sondern sucht noch nach einem Rest $6 und teilt den weiter auf.
In meinem Fall müsste der Rest als $5 als Value geschrieben werden.  :-\
Edit 3:So würde die Zeile 233 für mich arbeiten wie gewünscht:
anstatt
^(\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.*)?$
so
^(\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.*)?$

Wenn ich das richtig verstehe wird dann aber der "restliche Rest" $6 nie ermittelt.

Die letzte Zeile sieht dann wieder aus, wie das Original in der ersten Zeile:
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+
| TIMESTAMP           | DEVICE       | TYPE  | EVENT                 | READING     | VALUE         | UNIT |
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+
| 2019-08-19 13:12:35 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T: 23.1 H: 54 |      |
| 2019-08-19 13:12:36 | SensorAussen | DUMMY | state: T:  23.1 H: 54 | state       | T:            | 23.1 |
| 2019-08-19 13:12:37 | SensorAussen | DUMMY | state: T:23.1  H: 54  | state       | T:23.1        | H:   |
| 2019-08-19 13:12:39 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T:            | 23.1 |
| 2019-08-19 13:12:40 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T: 23.1 H: 54 |      |
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+


Für mich ist jetzt erstmal ein Weg da: Ich patche das Modul und verwende es so. Das funktioniert für mich :)
Meine Logs für Homematic Sensoren habe ich ganz am Anfang mal alle auf dies kurze "state Form" gesetzt. Erschien mir dadurch sehr sparsam im Log. Stellt sich jetzt im Nachgang etwas "hinderlich" dar! :)

Gruß Otto
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

DeeSPe

Zitat von: Otto123 am 19 August 2019, 14:17:48
Hi,

ich bin auf der Suche nach einem Fehlerfreiem Import von bisherigen LogFiles, deren Einträge so aussehen:
2018-12-31_23:56:15 SensorAussen T: 7.3 H: 90 D: 5.8
Der Eintrag der durch Import in der LogDb entsteht sieht dann so aus:
+---------------------+--------------+-------+-------------------------------+---------+--------------+------+
| TIMESTAMP           | DEVICE       | TYPE  | EVENT                         | READING | VALUE        | UNIT |
+---------------------+--------------+-------+-------------------------------+---------+--------------+------+
| 2018-12-31 23:56:15 | SensorAussen |       | T: 7.3 H: 90 D: 5.8           | T       | 7.3          | H:   |

Das ist nicht das was ich wollte. Nach einigen eigenen "Erkenntnissen" war klar: stateEvent fehlt.
Mein erster Versuch war diesen in die alten Logs einfach einzufügen:
sed 's/Aussen.T:/Aussen state T:/'Das funktioniert nicht sofort wie es sollte.  :'(

Da habe ich etwas weiter ausgeholt:
- FileLog um addStateEvent erweitert.
- LogDb und FilelLog haben jetzt einheitliches regExp: SensorAussen:.*
Nun habe ich neue "Referenzwerte" und weiß wie ich die alten Logs modifizieren muss. (Dachte ich)  ;)
Die Einträge sehen nun so aus:
Eintrag FileLog
2019-08-19_13:12:35 SensorAussen state: T: 23.1 H: 54

Eintrag DBLog
2019-08-19 13:12:35 | SensorAussen | DUMMY | state: T: 23.1 H: 54 | state       | T: 23.1 H: 54 |      |

Jetzt geh ich her und exportiere diese Zeile aus dem neuen FileLog in ein neues LogFile, modifiziere die Sekunde um eins und importiere anschließend diese eine Zeile wieder in die LogDB
cat /opt/fhem/log/SensorAussen-2019.log |grep -a "2019-08-19_13:12:35"|sed 's/:35/:36/'> /opt/fhem/log/SensorAussen-2019-1.log
Der Eintrag sieht dann so aus. Oben der Originale unten der importierte aus dem FileLog:
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+
| TIMESTAMP           | DEVICE       | TYPE  | EVENT                 | READING     | VALUE         | UNIT |
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+
| 2019-08-19 13:12:35 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T: 23.1 H: 54 |      |
| 2019-08-19 13:12:36 | SensorAussen | DUMMY | state: T:  23.1 H: 54 | state       | T:            | 23.1 |
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+

Wie man sieht wird ein Leerzeichen zwischen T: und 23.1 reingemogelt, welches offenbar zu dem fehlerhaften Import führt.
Für mich fällt mir jetzt keine Lösung ein, denn auch die Beseitigung des ursprünglichen Leerzeichens führt (fast erwartungsgemäß) nicht zum Erfolg: Aus "state: T:23.1 H: 54" wird dann "state: T:23.1  H: 54" also auch wieder ein Leerzeichen mehr drin, bloß weiter hinten :)

Hat jemand eine Idee?

Edit: Das Leerzeichen kommt aus Zeile 246 " $rest"
        $i_event .= " $rest" if ($rest);

Allerdings verhindert dort eine Änderung allein nicht die Aufteilung des Value
| 2019-08-19 13:12:39 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T:            | 23.1 |
Edit2:Das regExp in Zeile 233 nimmt nicht einfach alles nach dem ReadingName (state) als Value (wie es eigentlich geloggt wird ) sondern sucht noch nach einem Rest $6 und teilt den weiter auf.
In meinem Fall müsste der Rest als $5 als Value geschrieben werden.  :-\
Edit 3:So würde die Zeile 233 für mich arbeiten wie gewünscht:
anstatt
^(\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.*)?$
so
^(\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.*)?$

Wenn ich das richtig verstehe wird dann aber der "restliche Rest" $6 nie ermittelt.

Die letzte Zeile sieht dann wieder aus, wie das Original in der ersten Zeile:
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+
| TIMESTAMP           | DEVICE       | TYPE  | EVENT                 | READING     | VALUE         | UNIT |
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+
| 2019-08-19 13:12:35 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T: 23.1 H: 54 |      |
| 2019-08-19 13:12:36 | SensorAussen | DUMMY | state: T:  23.1 H: 54 | state       | T:            | 23.1 |
| 2019-08-19 13:12:37 | SensorAussen | DUMMY | state: T:23.1  H: 54  | state       | T:23.1        | H:   |
| 2019-08-19 13:12:39 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T:            | 23.1 |
| 2019-08-19 13:12:40 | SensorAussen | DUMMY | state: T: 23.1 H: 54  | state       | T: 23.1 H: 54 |      |
+---------------------+--------------+-------+-----------------------+-------------+---------------+------+


Für mich ist jetzt erstmal ein Weg da: Ich patche das Modul und verwende es so. Das funktioniert für mich :)
Meine Logs für Homematic Sensoren habe ich ganz am Anfang mal alle auf dies kurze "state Form" gesetzt. Erschien mir dadurch sehr sparsam im Log. Stellt sich jetzt im Nachgang etwas "hinderlich" dar! :)

Gruß Otto

Moin Otto,

uff, irgendwie sehe ich hier nicht mehr richtig durch. :o
Ich möchte Dir gern helfen, weiß nur gerade nicht so richtig wie.

Hast Du jetzt eine wirkliche Lösung für Dich gefunden und wenn ja welche?

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Otto123

#79
Guten Morgen Dan,

ja ich habe für mich eine Q&D Lösung gefunden:
1. Ich modifiziere meine Log Files vorm Import nach diesem Schema.
sed 's/Aussen.T:/Aussen state: T:/'
2. Ich verändere Zeile 233 in deinem Modul
Zitat^(\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.*)?$
Damit wird keine "UNIT" ermittelt und einfach alles nach state: als VALUE geschrieben. Damit sind die Werte erstmal richtig in der DB.

Das ist natürlich eine sehr händische Lösung und befriedigt mich nicht. :)
Ich probiere derzeit noch ein bisschen mit regEx und SQL Import um vielleicht doch eine direkte und automatische Lösung zu finden.

Und mein Ansatz ist natürlich auch falsch! Ich habe gerade nochmal in den Code geschaut:
Das Problem ist ja eher, dass Zeile 233 greift obwohl sie nicht dürfte und stattdessen Zeile 248 greifen müsste, was die aber auch nicht tun würde.

Bei meinem Logeintrag
2018-12-31_23:56:15 SensorAussen T: 7.3 H: 90 D: 5.8
wird T: als Reading erkannt -> Zeile 233 im Code greift.
Aber selbst wenn ich jetzt state: einfüge, greift dann wieder Zeile 233 und zerpflückt den "MultiValue"
Was übrigens auch mit solchen Zeilen von sysmon passiert:
2019-08-01_00:00:01 sysmon stat_cpu_percent: 1.57 0.00 2.02 96.38 0.02 0.00 0.01

Lass mich mal noch etwas probieren, vielleicht finde ich einen Ansatz. Ich denke aber man muss noch ein paar "Schalter" für Spezialfälle einbauen. Oder ist es schon da und ich habe es nicht gesehen?

Ich finde auf alle Fälle durch Zeile 246 werden die Daten "verfälscht" - aber kann sein ich habe den Sinn von dem Leerzeichen nicht verstanden:
$i_event .= " $rest" if ($rest);
die sollte so aussehen
$i_event .= "$rest" if ($rest);

Edit:
Da in Zeile 248 ff keine Unit ermittelt wird, kann doch dort wenigsten der "komplette Rest" als Value eingetragen werden? Ich würde denken, dort wäre das regEx richtiger so:
($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s([A-Za-z0-9\.\-_].*)$/)
anstatt
($line =~ /^(\d{4}-\d{2}-\d{2})_(\d{2}:\d{2}:\d{2})\s([A-Za-z0-9\.\-_]+)\s([A-Za-z0-9\.\-_]+)$/)
Damit kommt auch der "Multivalue" komplett in die Datenbank, ansonsten bloß der erste Wert

Ist Zeile 257 eigentlich dann konsequent?
$i_event = $i_value;
Ja der Event war so, aber eigentlich wurde er ja um state: korrigiert :) und DbLog macht es doch auch so? DbLog schreibt doch auch den state dazu? Oder habe ich das an irgendeiner Stelle getan? Ich sehe es nicht, ich habe nur beim FileLog addStateEvent gesetzt.

Eigentlich wäre mein Fall (der aber sicher nicht für mich speziell ist) dadurch gelöst wenn man den Import mit "addStateEvent" erzwingen kann und das regEx in Zeile 248 nach meinem Vorschlag abgeändert wird.

LG Otto

P.S. sorry wieder viel Text :)
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

Otto123

Ist vielleicht etwas OT aber ich habe mal mit SQL experimentiert.
Ein Script welches ein LOG welches keine Readings enthält, also das typische "state: fehlt Log" :)
Liest sich durch den SQL Syntax etwas sperrig :) und ich habe von SQL quasi keine Ahnung (kann also sein, dass der Code peinlich ist)
LOAD DATA LOCAL INFILE '/opt/fhem/log/SensorAussen-2017.log'
INTO TABLE history (@col1)
set TIMESTAMP=REGEXP_REPLACE(REGEXP_SUBSTR(@col1, '^[0-9-_:]{19}'), '_', ' '),
DEVICE=REGEXP_SUBSTR(@col1, '[[:alpha:]]+'),
READING='state',
VALUE=SUBSTRING(SUBSTRING(@col1, REGEXP_INSTR(@col1, '[[:space:]]')+1) ,REGEXP_INSTR(SUBSTRING(@col1, REGEXP_INSTR(@col1, '[[:space:]]')+1), '[[:space:]]')+1),
EVENT=CONCAT(READING,': ',VALUE),
TYPE='',
UNIT=''
;
Der Import dauert  ca. 6 sec! Mit dem Modul dauert der Import ca. 2h.
Die Original Filelog Zeile:
2017-08-29_14:40:00 SensorAussen T: 29.0 H: 50 D: 17.5
Das Ergebnis im SQL Server:
+---------------------+--------------+------+------------------------------+---------+-----------------------+------+
| TIMESTAMP           | DEVICE       | TYPE | EVENT                        | READING | VALUE                 | UNIT |
+---------------------+--------------+------+------------------------------+---------+-----------------------+------+
| 2017-08-29 14:40:00 | SensorAussen |      | state: T: 29.0 H: 50 D: 17.5 | state   | T: 29.0 H: 50 D: 17.5 |      |
+---------------------+--------------+------+------------------------------+---------+-----------------------+------+


Vielleicht kann man das ja irgendwie im Modul einheiraten, wenn mal "saure Gurken Zeit" ist. 

Gruß Otto
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

ddw

@Otto123: Ich hatte ein ähnliches Problem, es dauerte teilweise > 12h, eine Logddatei zu importieren.

In den sourcen hab ich gesehen, dass der Code für jedes Logevent einen einzelnen SQL-Aufruf durchführt, das ist zwar so atomar wie nur möglich, aber eben aufwändig, was man bei langen Logfiles zu spüren bekommt.

Ich hab den Code für mich so (minimal) erweitert, dass immer eine gewisse Zahl (ich hab 1000 verwendet) Logeinträge eingelesen und dann auf einmal in einem SQL-Insert eingefügt werden. Das funktionierte bei mir wunderbar, aber ich bin weder Perl-Programmierer noch hab ich mich in die FHEM-Umgebung eingelesen. Bei mir hat das die Verarbeitungszeiten von >10 Stunden auf wenige Minuten für Logfiles ähnlicher Grö0ße gebracht.

@DeeSPe: magst Du Dir mal den angehängten Diff anschauen? Vielleicht könntest Du das ja in das Modul übernehmen.
Aber erstmal: vielen Dank fürs Schreiben des Moduls an sich! Ohne das hätte ich weiter nicht auf logdb gewechselt, sondern auf mittlere Sicht beides parallel laufen lassen.

diff orig/98_FileLogConvert.pm ddw/98_FileLogConvert.pm
175a176
>   my $rows_per_query = 1000;
211a213,214
>   my $query = "";
>   my $qrows = 0;
267c270,288
<       DbLog_ExecSQL($defs{$dblog},$ret) if ($cmd eq "import2DbLog");
---
>       if ($cmd eq "import2DbLog") # Line n-2 not changed to keep old structure and diff small.
>       {
>         $ret = "('$i_date $i_time','$i_device','$i_type','$i_event','$i_reading','$i_value','$i_unit')";
>         if ($query eq "")
>         {
>           $query = $ret;
>         }
>         else
>         {
>           $query = $query . "," . $ret; # string manipulation is expensive, but not as expensive as SQL-calls
>         }
>         $qrows++;
>         if ($qrows == $rows_per_query)
>         {
>           DbLog_ExecSQL($defs{$dblog},"INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES " . $query . ";");
>           $query = "";
>           $qrows = 0;
>         }
>       }
269a291,296
>   }
>   if ($query ne "") # könnte noch ein Assert ($cmd eq "import2DbLog" && $qrows>0) vertragen
>   {
>     DbLog_ExecSQL($defs{$dblog},"INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES " . $query . ";");
>     $query = "";
>     $qrows = 0;


DeeSPe

Zitat von: ddw am 27 Oktober 2019, 19:22:52
@Otto123: Ich hatte ein ähnliches Problem, es dauerte teilweise > 12h, eine Logddatei zu importieren.

In den sourcen hab ich gesehen, dass der Code für jedes Logevent einen einzelnen SQL-Aufruf durchführt, das ist zwar so atomar wie nur möglich, aber eben aufwändig, was man bei langen Logfiles zu spüren bekommt.

Ich hab den Code für mich so (minimal) erweitert, dass immer eine gewisse Zahl (ich hab 1000 verwendet) Logeinträge eingelesen und dann auf einmal in einem SQL-Insert eingefügt werden. Das funktionierte bei mir wunderbar, aber ich bin weder Perl-Programmierer noch hab ich mich in die FHEM-Umgebung eingelesen. Bei mir hat das die Verarbeitungszeiten von >10 Stunden auf wenige Minuten für Logfiles ähnlicher Grö0ße gebracht.

@DeeSPe: magst Du Dir mal den angehängten Diff anschauen? Vielleicht könntest Du das ja in das Modul übernehmen.
Aber erstmal: vielen Dank fürs Schreiben des Moduls an sich! Ohne das hätte ich weiter nicht auf logdb gewechselt, sondern auf mittlere Sicht beides parallel laufen lassen.

diff orig/98_FileLogConvert.pm ddw/98_FileLogConvert.pm
175a176
>   my $rows_per_query = 1000;
211a213,214
>   my $query = "";
>   my $qrows = 0;
267c270,288
<       DbLog_ExecSQL($defs{$dblog},$ret) if ($cmd eq "import2DbLog");
---
>       if ($cmd eq "import2DbLog") # Line n-2 not changed to keep old structure and diff small.
>       {
>         $ret = "('$i_date $i_time','$i_device','$i_type','$i_event','$i_reading','$i_value','$i_unit')";
>         if ($query eq "")
>         {
>           $query = $ret;
>         }
>         else
>         {
>           $query = $query . "," . $ret; # string manipulation is expensive, but not as expensive as SQL-calls
>         }
>         $qrows++;
>         if ($qrows == $rows_per_query)
>         {
>           DbLog_ExecSQL($defs{$dblog},"INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES " . $query . ";");
>           $query = "";
>           $qrows = 0;
>         }
>       }
269a291,296
>   }
>   if ($query ne "") # könnte noch ein Assert ($cmd eq "import2DbLog" && $qrows>0) vertragen
>   {
>     DbLog_ExecSQL($defs{$dblog},"INSERT INTO history (TIMESTAMP,DEVICE,TYPE,EVENT,READING,VALUE,UNIT) VALUES " . $query . ";");
>     $query = "";
>     $qrows = 0;


Hallo ddw,

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

Danke.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Beta-User

Vielleicht noch was zum Thema "mehrere Dateien".

Habe mir folgendes gebaut, um meine alten Daten (teilweise) einzulesen, ohne dabei jeweils auf den Abschluss des laufenden Prozesses warten zu müssen oder jede Datei einzeln anzugeben. Besteht aus zwei userAttr am FileLogConvert-Gerät, einem notify und etwas myUtils-Code.

Ist evtl. was, was man auch in das Modul einbauen könnte (aber vermutlich noch einfacher zu bedienen, wenn man einen Zeilenwechsel für das split verwendet und "list -1"-Output für's füllen des myFiles-Attributs.

Das mit Attribut zu machen, ist zwar nicht optimal, aber das ganze ist ja keine Dauerlösung, sondern man braucht es einmalig. Abbrechen geht darüber (nach dem Ende des laufenden Imports, indem man eben das Attribut bzw. den Inhalt ändert:

defmod flc FileLogConvert LogDB
attr flc userattr myRegex myFiles
attr flc myFiles Thermostat_Bad_OG-2016.log Thermostat_Bad_OG-2017.log Thermostat_Buero-2016.log Thermostat_Buero-2017.log
attr flc myRegex (actuator|batteryLevel|desired-temp|measured-temp).*


defmod n_flc_next notify flc:import.done {flc_next($NAME)}

Start entweder über eine nicht im Attribut gelistete FileLog-file oder z.B. mit
trigger flc import done

##############################################
# $Id: myUtils_Testing.pm 2019-10-30 Beta-User $
#

package main;

use strict;
use warnings;
use POSIX;

sub
myUtils_Testing_Initialize($$)
{
  my ($hash) = @_;
}

# Enter you functions below _this_ line.

sub flc_next($) {
  my $device = shift (@_);
  my $regxp = AttrVal($device,"myRegex",".*");
  my $myfiles = AttrVal($device,"myFiles","");
  my @files = split(' ',$myfiles);
  return undef unless (@files);
  my $file = shift (@files);
  CommandSet(undef, "$device import2DbLog $file $regxp");
  if (@files) {
    $file = join (" ",@files);
  } else {
    $file = "";
  }
  CommandAttr(undef, "$device myFiles $file");
}

1;


Danke auf alle Fälle für die Import-Funktion!
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

JimKnopf

Hallo Zusammen!

Ich stelle auch gerade bei mir alles auf DbLog um. Die Max Heizkörper und WM-Bus Gaszähler haben prima geklappt. Jetzt hängt es an den Logs von CUL_EM, das sind Mess-Steckdosen von ELV.
Die Filelog Einträge sehen so aus:
2020-01-02_12:13:49 EM_Kuehlschrank CNT: 131 CUM: 286.898  5MIN: 0.000  TOP: 0.000
Damit kommt LogConvert nicht zurecht.
Wie kann ich diese Einiträge am einfachsten importieren?

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

Hi,

wenn Du ein paar Einträge (bis #77) zurück gehst und liest, weißt Du warum und wie man es machen kann.

Gruß Otto
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

Hi!

Entweder bin ich zu doof und erkenne nicht, was mir im Beitrag #77 helfen soll oder meine Voraussetzungen sind anders.
addStateEvent  bezieht sich ja nur auf neue Einträge, mit denen hab ich kein Problem, denn die Werte werden von logdb perfekt mitgeschrieben.
Es geht um die Logs der letzten 4 Jahre.  Dafür habe ich in dem Beitrag keine Lösung gefunden.

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

Ich habe nicht gesagt im Beitrag 77 - aber dort fängt es an, da kommen ein paar Beiträge von mir. Das gleiche Problem wie bei Dir. Du musst halt eine halb "manuelle" Lösung schaffen. Diese "state" Logs sind für FileLog toll für dblog sind sie witzlos, Ich kann nur davon abraten mehrere Werte in einen Wert der Db zu loggen und sie dann beim plotten wieder zu zerlegen. Dauert sinnlos lange. Ich habe keine Weg gefunden es effizient zu machen.
Sorry ich will das nicht nochmal alles für deine Werte durchdenken. Ich habe das mittlerweile sein lassen, weil die ganze Arbeit überhaupt keinen Vorteil bringt.
Du bist mit deinen Programmier Kenntnissen sicher schneller, wenn Du ein sql Script baust, was Deine Datenstruktur berücksichtigt.
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

Hi !
Danke für die Antwort, damit kann ich arbeiten  ;).
Ich werde dann wohl ein C++ Programm schreiben, dass ein beliebiges Logfile einlesen kann und jede einzelne Zeile mit Multieinträgen in einzelne Zeilen aufteilt. Z.B.
aus
2020-01-02_12:13:49 EM_Kuehlschrank CNT: 131 CUM: 286.898  5MIN: 0.000  TOP: 0.000

wird dann:
2020-01-02_12:13:49 EM_Kuehlschrank CNT: 131
2020-01-02_12:13:49 EM_Kuehlschrank CUM: 286.898
2020-01-02_12:13:49 EM_Kuehlschrank 5MIN: 0.000
2020-01-02_12:13:49 EM_Kuehlschrank TOP: 0.000

das sollte man ja sicher importieren können.
Leider kann ich kein Perl, da könnte man das sicher gleich in LogConvert einbauen, wenn ein Logfile eingelesen wird, dass Mutliwerte enthält.

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

Ich denke das ist der richtige Weg :)
Aber Du kann es auch gleich in die Datenbank schreiben, die ist doch unabhängig von FHEM erreichbar.
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