2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-01 01:09:47 +00:00

93_DbLog: contrib 5.5.3

git-svn-id: https://svn.fhem.de/fhem/trunk@26828 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2022-12-10 15:15:20 +00:00
parent 4fcbaace1b
commit 98a05dd7aa

View File

@ -2103,7 +2103,7 @@ sub DbLog_execMemCacheAsync {
$memc->{cdataindex} = $data{DbLog}{$name}{cache}{index}; # aktuellen Index an Subprozess übergeben $memc->{cdataindex} = $data{DbLog}{$name}{cache}{index}; # aktuellen Index an Subprozess übergeben
undef $data{DbLog}{$name}{cache}{memcache}; # sicherheitshalber Memory freigeben: https://perlmaven.com/undef-on-perl-arrays-and-hashes , bzw. https://www.effectiveperlprogramming.com/2018/09/undef-a-scalar-to-release-its-memory/ undef %{$data{DbLog}{$name}{cache}{memcache}}; # sicherheitshalber Memory freigeben: https://perlmaven.com/undef-on-perl-arrays-and-hashes , bzw. https://www.effectiveperlprogramming.com/2018/09/undef-a-scalar-to-release-its-memory/
$error = DbLog_SBP_sendLogData ($hash, 'log_asynch', $memc); # Subprocess Prozessdaten senden, Log-Daten sind in $memc->{cdata} gespeichert $error = DbLog_SBP_sendLogData ($hash, 'log_asynch', $memc); # Subprocess Prozessdaten senden, Log-Daten sind in $memc->{cdata} gespeichert
return if($error); return if($error);
@ -2156,7 +2156,7 @@ sub DbLog_execMemCacheSync {
my $memc; my $memc;
for my $key (sort(keys %{$data{DbLog}{$name}{cache}{memcache}})) { for my $key (sort(keys %{$data{DbLog}{$name}{cache}{memcache}})) {
Log3 ($name, 5, "DbLog $name - Store contains: $key -> ".$data{DbLog}{$name}{cache}{memcache}{$key}); Log3 ($name, 5, "DbLog $name - TempStore contains: $key -> ".$data{DbLog}{$name}{cache}{memcache}{$key});
$memc->{cdata}{$key} = delete $data{DbLog}{$name}{cache}{memcache}{$key}; # Subprocess Daten, z.B.: 2022-11-29 09:33:32|SolCast|SOLARFORECAST||nextCycletime|09:33:47| $memc->{cdata}{$key} = delete $data{DbLog}{$name}{cache}{memcache}{$key}; # Subprocess Daten, z.B.: 2022-11-29 09:33:32|SolCast|SOLARFORECAST||nextCycletime|09:33:47|
} }
@ -2241,7 +2241,7 @@ sub DbLog_SBP_onRun {
} }
if ($dbstorepars) { # DB Verbindungsparameter speichern if ($dbstorepars) { # DB Verbindungsparameter speichern
Log3 ($name, 3, "DbLog $name - DB connection parameters are stored in SubProcess ..."); Log3 ($name, 3, "DbLog $name - DB connection parameters are stored in SubProcess");
$store->{dbparams}{dbconn} = $memc->{dbconn}; $store->{dbparams}{dbconn} = $memc->{dbconn};
$store->{dbparams}{dbname} = (split /;|=/, $memc->{dbconn})[1]; $store->{dbparams}{dbname} = (split /;|=/, $memc->{dbconn})[1];
@ -2256,7 +2256,14 @@ sub DbLog_SBP_onRun {
$store->{dbparams}{current} = $memc->{current}; # Name current-Tabelle $store->{dbparams}{current} = $memc->{current}; # Name current-Tabelle
$store->{dbparams}{dbstorepars} = $memc->{dbstorepars}; # Status Speicherung DB Parameter 0|1 $store->{dbparams}{dbstorepars} = $memc->{dbstorepars}; # Status Speicherung DB Parameter 0|1
Log3 ($name, 5, "DbLog $name - DB Parameter stored in SubProcess: \n".Dumper $store->{dbparams}); if ($verbose == 5) {
Log3 ($name, 5, "DbLog $name - DB Parameter stored in SubProcess:");
for my $dbp (sort keys %{$store->{dbparams}}) {
next if(!defined $store->{dbparams}{$dbp});
Log3 ($name, 5, "DbLog $name - $dbp -> ".$store->{dbparams}{$dbp});
}
}
$ret = { $ret = {
name => $name, name => $name,
@ -2277,6 +2284,7 @@ sub DbLog_SBP_onRun {
for my $idx (sort {$a<=>$b} keys %{$cdata}) { for my $idx (sort {$a<=>$b} keys %{$cdata}) {
$logstore->{$idx} = $cdata->{$idx}; $logstore->{$idx} = $cdata->{$idx};
Log3 ($name, 4, "DbLog $name - stored: $idx -> ".$logstore->{$idx}); Log3 ($name, 4, "DbLog $name - stored: $idx -> ".$logstore->{$idx});
} }
@ -2365,8 +2373,6 @@ sub DbLog_SBP_onRun {
$subprocess->writeToParent($retjson); $subprocess->writeToParent($retjson);
next; next;
} }
Log3 ($name, 3, "DbLog $name - SubProcess connected to $store->{dbparams}{dbname}");
}; };
@ -2587,14 +2593,19 @@ sub _DbLog_SBP_onRun_Log {
Log3 ($name, 5, "DbLog $name - Primary Key usage suppressed by attribute noSupportPK"); Log3 ($name, 5, "DbLog $name - Primary Key usage suppressed by attribute noSupportPK");
} }
if (defined $logstore) { # temporär gespeicherte Daten hinzufügen
for my $index (sort {$a<=>$b} keys %{$logstore}) {
$cdata->{$index} = $logstore->{$index};
my $ln = scalar keys %{$logstore};
if ($ln) { # temporär gespeicherte Daten hinzufügen
for my $index (sort {$a<=>$b} keys %{$logstore}) {
Log3 ($name, 4, "DbLog $name - add stored data: $index -> ".$logstore->{$index}); Log3 ($name, 4, "DbLog $name - add stored data: $index -> ".$logstore->{$index});
$cdata->{$index} = delete $logstore->{$index};
} }
undef $logstore; undef %{$logstore};
Log3 ($name, 4, "DbLog $name - logstore deleted - $ln stored datasets added for processing");
} }
my $ceti = scalar keys %{$cdata}; my $ceti = scalar keys %{$cdata};
@ -2691,6 +2702,8 @@ sub _DbLog_SBP_onRun_Log {
return; return;
}; };
__DbLog_SBP_commitOnly ($name, $dbh, $history);
if($ins_hist == $ceti) { if($ins_hist == $ceti) {
Log3 ($name, 4, "DbLog $name - $ins_hist of $ceti events inserted into table $history".($usepkh ? " using PK on columns $pkh" : "")); Log3 ($name, 4, "DbLog $name - $ins_hist of $ceti events inserted into table $history".($usepkh ? " using PK on columns $pkh" : ""));
} }
@ -2919,6 +2932,17 @@ sub _DbLog_SBP_onRun_Log {
} }
} }
} }
if(defined $rowhref) { # nicht gespeicherte Datensätze ausgeben
Log3 ($name, 2, "DbLog $name - The following data are faulty and were not saved:");
for my $df (sort {$a <=>$b} keys %{$rowhref}) {
Log3 ($name, 2, "DbLog $name - $rowhref->{$df}");
}
}
__DbLog_SBP_commitOnly ($name, $dbh, $history);
1; 1;
} }
or do { $error = $@; or do { $error = $@;
@ -2930,7 +2954,7 @@ sub _DbLog_SBP_onRun_Log {
__DbLog_SBP_rollbackOnly ($name, $dbh, $history); __DbLog_SBP_rollbackOnly ($name, $dbh, $history);
} }
else { else {
if(defined $rowhref) { # nicht gespeicherte Datensätze ausgeben if(defined $rowhref) { # nicht gespeicherte Datensätze ausgeben
Log3 ($name, 2, "DbLog $name - The following data are faulty and were not saved:"); Log3 ($name, 2, "DbLog $name - The following data are faulty and were not saved:");
for my $df (sort {$a <=>$b} keys %{$rowhref}) { for my $df (sort {$a <=>$b} keys %{$rowhref}) {
@ -4412,7 +4436,7 @@ sub DbLog_SBP_Read {
if($reqdbdat) { # Übertragung DB Verbindungsparameter ist requested if($reqdbdat) { # Übertragung DB Verbindungsparameter ist requested
my $rst = DbLog_SBP_sendConnectionData ($hash); my $rst = DbLog_SBP_sendConnectionData ($hash);
if (!$rst) { if (!$rst) {
Log3 ($name, 3, "DbLog $name - requested DB connection parameters are transmitted ..."); Log3 ($name, 3, "DbLog $name - requested DB connection parameters are transmitted");
} }
} }
@ -7381,47 +7405,67 @@ return;
</ul> </ul>
<br> <br>
<ul>
<li><b>set &lt;name&gt; addCacheLine YYYY-MM-DD HH:MM:SS|&lt;device&gt;|&lt;type&gt;|&lt;event&gt;|&lt;reading&gt;|&lt;value&gt;|[&lt;unit&gt;] </b> <br><br>
<ul>
Im asynchronen Modus wird ein neuer Datensatz in den Cache eingefügt und beim nächsten Synclauf mit abgearbeitet.
<br><br>
<b>Beispiel:</b> <br>
set &lt;name&gt; addCacheLine 2017-12-05 17:03:59|MaxBathRoom|MAX|valveposition: 95|valveposition|95|% <br>
</li>
</ul>
<br>
<li><b>set &lt;name&gt; addLog &lt;devspec&gt;:&lt;Reading&gt; [Value] [CN=&lt;caller name&gt;] [!useExcludes] </b> <br><br> <li><b>set &lt;name&gt; addLog &lt;devspec&gt;:&lt;Reading&gt; [Value] [CN=&lt;caller name&gt;] [!useExcludes] </b> <br><br>
<ul> <ul>
Inserts an additional log entry of a device/reading combination into the database. Readings which are possibly specified Inserts an additional log entry of a device/reading combination into the database. <br>
in attribute "DbLogExclude" (in source device) are not logged, unless they are enclosed in attribute "DbLogInclude" Any readings specified in the "DbLogExclude" attribute (in the source device) will not be logged, unless
or addLog was called with option "!useExcludes". <br><br> they are included in the "DbLogInclude" attribute or the addLog call was made with the "!useExcludes" option.
<br><br>
<ul> <table>
<li> <b>&lt;devspec&gt;:&lt;Reading&gt;</b> - The device can be declared by a <a href="#devspec">device specification <colgroup> <col width=20%> <col width=80%> </colgroup>
(devspec)</a>. "Reading" will be evaluated as regular expression. If <tr><td> <b>&lt;devspec&gt;:&lt;Reading&gt;</b> </td><td>The device can be specified as <a href="#devspec">device specification</a>. </td></tr>
The reading isn't available and the value "Value" is specified, the <tr><td> </td><td>The specification of "Reading" is evaluated as a regular expression. </td></tr>
reading will be added to database as new one if it isn't a regular <tr><td> </td><td>If the reading does not exist and the value "Value" is specified, the reading </td></tr>
expression and the readingname is valid. </li> <tr><td> </td><td>will be inserted into the DB if it is not a regular expression and a valid reading name. </td></tr>
<li> <b>Value</b> - Optionally you can enter a "Value" that is used as reading value in the dataset. If the value isn't <tr><td> </td><td> </td></tr>
specified (default), the current value of the specified reading will be inserted into the database. </li> <tr><td> </td><td> </td></tr>
<li> <b>CN=&lt;caller name&gt;</b> - By the key "CN=" (<b>C</b>aller <b>N</b>ame) you can specify an additional string, <tr><td> <b>Value</b> </td><td>Optionally, "Value" can be specified for the reading value. </td></tr>
e.g. the name of a calling device (for example an at- or notify-device). <tr><td> </td><td>If Value is not specified, the current value of the reading is inserted into the DB. </td></tr>
Via the function defined in <a href="#DbLog-attr-valueFn">valueFn</a> this key can be analyzed <tr><td> </td><td> </td></tr>
by the variable $CN. Thereby it is possible to control the behavior of the addLog dependend from <tr><td> </td><td> </td></tr>
the calling source. </li> <tr><td> <b>CN=&lt;caller name&gt;</b> </td><td>With the key "CN=" (<b>C</b>aller <b>N</b>ame) a string, e.g. the name of the calling device, </td></tr>
<li> <b>!useExcludes</b> - The function considers attribute "DbLogExclude" in the source device if it is set. If the optional <tr><td> </td><td>can be added to the addLog call. </td></tr>
keyword "!useExcludes" is set, the attribute "DbLogExclude" isn't considered. </li> <tr><td> </td><td>With the help of the function stored in the attribute <a href="#DbLog-attr-valueFn">valueFn</a> </td></tr>
</ul> <tr><td> </td><td>this key can be evaluated via the variable $CN. </td></tr>
<tr><td> </td><td> </td></tr>
<tr><td> <b>!useExcludes</b> </td><td>addLog by default takes into account the readings excluded with the "DbLogExclude" attribute. </td></tr>
<tr><td> </td><td>With the keyword "!useExcludes" the set attribute "DbLogExclude" is ignored. </td></tr>
</table>
<br> <br>
The database field "EVENT" will be filled with the string "addLog" automatically. <br> The database field "EVENT" is automatically filled with "addLog". <br>
The addLog-command dosn't create an additional event in your system !<br><br> There will be <b>no</b> additional event created in the system! <br><br>
<b>Examples:</b> <br> <b>Examples:</b> <br>
set &lt;name&gt; addLog SMA_Energymeter:Bezug_Wirkleistung <br> set &lt;name&gt; addLog SMA_Energymeter:Bezug_Wirkleistung <br>
set &lt;name&gt; addLog TYPE=SSCam:state <br> set &lt;name&gt; addLog TYPE=SSCam:state <br>
set &lt;name&gt; addLog MyWetter:(fc10.*|fc8.*) <br> set &lt;name&gt; addLog MyWetter:(fc10.*|fc8.*) <br>
set &lt;name&gt; addLog MyWetter:(wind|wind_ch.*) 20 !useExcludes <br> set &lt;name&gt; addLog MyWetter:(wind|wind_ch.*) 20 !useExcludes <br>
set &lt;name&gt; addLog TYPE=CUL_HM:FILTER=model=HM-CC-RT-DN:FILTER=subType!=(virtual|):(measured-temp|desired-temp|actuator) <br><br> set &lt;name&gt; addLog TYPE=CUL_HM:FILTER=model=HM-CC-RT-DN:FILTER=subType!=(virtual|):(measured-temp|desired-temp|actuator) <br><br>
set &lt;name&gt; addLog USV:state CN=di.cronjob <br> set &lt;name&gt; addLog USV:state CN=di.cronjob <br><br>
In the valueFn-function the caller "di.cronjob" is evaluated via the variable $CN and the timestamp is corrected: <br><br>
valueFn = if($CN eq "di.cronjob" and $TIMESTAMP =~ m/\s00:00:[\d:]+/) { $TIMESTAMP =~ s/\s([^\s]+)/ 23:59:59/ }
</li> In the valueFn function the caller "di.cronjob" is evaluated via the variable $CN and depending on this the
timestamp of this addLog is corrected: <br><br>
valueFn = if($CN eq "di.cronjob" and $TIMESTAMP =~ m/\s00:00:[\d:]+/) { $TIMESTAMP =~ s/\s([^\s]+)/ 23:59:59/ }
</ul> </ul>
</li>
<br> <br>
<li><b>set &lt;name&gt; clearReadings </b> <br><br> <li><b>set &lt;name&gt; clearReadings </b> <br><br>
@ -8951,42 +8995,48 @@ attr SMA_Energymeter DbLogValueFn
<ul> <ul>
Fügt einen zusätzlichen Logeintrag einer Device/Reading-Kombination in die Datenbank ein. <br> Fügt einen zusätzlichen Logeintrag einer Device/Reading-Kombination in die Datenbank ein. <br>
Die eventuell im Attribut "DbLogExclude" spezifizierten Readings (im Quellendevice) werden nicht geloggt, es sei denn Die eventuell im Attribut "DbLogExclude" spezifizierten Readings (im Quellendevice) werden nicht geloggt, es sei denn
sie sind im Attribut "DbLogInclude" enthalten bzw. der addLog Aufruf erfolgte mit der Option "!useExcludes". <br><br> sie sind im Attribut "DbLogInclude" enthalten bzw. der addLog Aufruf erfolgte mit der Option "!useExcludes".
<br><br>
<ul> <table>
<li> <b>&lt;devspec&gt;:&lt;Reading&gt;</b> - Das Device kann als <a href="#devspec">Geräte-Spezifikation</a> angegeben werden. <br> <colgroup> <col width=20%> <col width=80%> </colgroup>
Die Angabe von "Reading" wird als regulärer Ausdruck ausgewertet. Ist <tr><td> <b>&lt;devspec&gt;:&lt;Reading&gt;</b> </td><td>Das Device kann als <a href="#devspec">Geräte-Spezifikation</a> angegeben werden. </td></tr>
das Reading nicht vorhanden und der Wert "Value" angegeben, wird das Reading <tr><td> </td><td>Die Angabe von "Reading" wird als regulärer Ausdruck ausgewertet. </td></tr>
in die DB eingefügt wenn es kein regulärer Ausdruck und ein valider <tr><td> </td><td>Ist das Reading nicht vorhanden und der Wert "Value" angegeben, wird das Reading </td></tr>
Readingname ist. </li> <tr><td> </td><td>in die DB eingefügt wenn es kein regulärer Ausdruck und ein valider Readingname ist. </td></tr>
<li> <b>Value</b> - Optional kann "Value" für den Readingwert angegeben werden. Ist Value nicht angegeben, wird der aktuelle <tr><td> </td><td> </td></tr>
Wert des Readings in die DB eingefügt. </li> <tr><td> </td><td> </td></tr>
<li> <b>CN=&lt;caller name&gt;</b> - Mit dem Schlüssel "CN=" (<b>C</b>aller <b>N</b>ame) kann dem addLog-Aufruf ein String, <tr><td> <b>Value</b> </td><td>Optional kann "Value" für den Readingwert angegeben werden. </td></tr>
z.B. der Name des aufrufenden Devices (z.B. eines at- oder notify-Devices), mitgegeben <tr><td> </td><td>Ist Value nicht angegeben, wird der aktuelle Wert des Readings in die DB eingefügt. </td></tr>
werden. Mit Hilfe der im <a href="#DbLog-attr-valueFn">valueFn</a> hinterlegten <tr><td> </td><td> </td></tr>
Funktion kann dieser Schlüssel über die Variable $CN ausgewertet werden. Dadurch ist es <tr><td> </td><td> </td></tr>
möglich, das Verhalten des addLogs abhängig von der aufrufenden Quelle zu beeinflussen. <tr><td> <b>CN=&lt;caller name&gt;</b> </td><td>Mit dem Schlüssel "CN=" (<b>C</b>aller <b>N</b>ame) kann dem addLog-Aufruf ein String, </td></tr>
</li> <tr><td> </td><td>z.B. der Name des aufrufenden Devices, mitgegeben werden. </td></tr>
<li> <b>!useExcludes</b> - Ein eventuell im Quell-Device gesetztes Attribut "DbLogExclude" wird von der Funktion berücksichtigt. Soll dieses <tr><td> </td><td>Mit Hilfe der im Attribut <a href="#DbLog-attr-valueFn">valueFn</a> hinterlegten Funktion kann </td></tr>
Attribut nicht berücksichtigt werden, kann das Schüsselwort "!useExcludes" verwendet werden. </li> <tr><td> </td><td>dieser Schlüssel über die Variable $CN ausgewertet werden. </td></tr>
</ul> <tr><td> </td><td> </td></tr>
<tr><td> </td><td> </td></tr>
<tr><td> <b>!useExcludes</b> </td><td>addLog berücksichtigt per default die mit dem Attribut "DbLogExclude" ausgeschlossenen Readings. </td></tr>
<tr><td> </td><td>Mit dem Schüsselwort "!useExcludes" wird das gesetzte Attribut "DbLogExclude" ignoriert. </td></tr>
</table>
<br> <br>
Das Datenbankfeld "EVENT" wird automatisch mit "addLog" belegt. <br> Das Datenbankfeld "EVENT" wird automatisch mit "addLog" belegt. <br>
Es wird KEIN zusätzlicher Event im System erzeugt !<br><br> Es wird <b>kein</b> zusätzlicher Event im System erzeugt! <br><br>
<b>Beispiele:</b> <br> <b>Beispiele:</b> <br>
set &lt;name&gt; addLog SMA_Energymeter:Bezug_Wirkleistung <br> set &lt;name&gt; addLog SMA_Energymeter:Bezug_Wirkleistung <br>
set &lt;name&gt; addLog TYPE=SSCam:state <br> set &lt;name&gt; addLog TYPE=SSCam:state <br>
set &lt;name&gt; addLog MyWetter:(fc10.*|fc8.*) <br> set &lt;name&gt; addLog MyWetter:(fc10.*|fc8.*) <br>
set &lt;name&gt; addLog MyWetter:(wind|wind_ch.*) 20 !useExcludes <br> set &lt;name&gt; addLog MyWetter:(wind|wind_ch.*) 20 !useExcludes <br>
set &lt;name&gt; addLog TYPE=CUL_HM:FILTER=model=HM-CC-RT-DN:FILTER=subType!=(virtual|):(measured-temp|desired-temp|actuator) <br><br> set &lt;name&gt; addLog TYPE=CUL_HM:FILTER=model=HM-CC-RT-DN:FILTER=subType!=(virtual|):(measured-temp|desired-temp|actuator) <br><br>
set &lt;name&gt; addLog USV:state CN=di.cronjob <br> set &lt;name&gt; addLog USV:state CN=di.cronjob <br><br>
In der valueFn-Funktion wird der Aufrufer "di.cronjob" über die Variable $CN ausgewertet und davon abhängig der In der valueFn-Funktion wird der Aufrufer "di.cronjob" über die Variable $CN ausgewertet und davon abhängig der
Timestamp dieses addLog korrigiert: <br><br> Timestamp dieses addLog korrigiert: <br><br>
valueFn = if($CN eq "di.cronjob" and $TIMESTAMP =~ m/\s00:00:[\d:]+/) { $TIMESTAMP =~ s/\s([^\s]+)/ 23:59:59/ }
valueFn = if($CN eq "di.cronjob" and $TIMESTAMP =~ m/\s00:00:[\d:]+/) { $TIMESTAMP =~ s/\s([^\s]+)/ 23:59:59/ }
</ul> </ul>
</li> </li>
<br> <br>