Es tut mir echt leid... schon wieder eine Frage zu DbLog bzw. DbRep...
Anstatt erst viele Daten im DbLog zu speichern und dann zu filtern, versuche ich, von Anfang an weniger Daten zu speichern. Deswegen schreibe ich statt alles per Event zu loggen in einigen Bereichen regelmäßig errechnete Daten in die DB:
fhem("set DBRep_Strom sqlCmd INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ('$CurEnergyTS', '$Shelly', 'MQTT2_DEVICE', 'calcPower: $energy_diff_in_Ws', 'calcPower', '$energy_diff_in_Ws', '');");
Commandref sagt zu sqlCmd von DbRep:
ZitatHinweis:
Auch wenn das Modul bezüglich der Datenbankabfrage nichtblockierend arbeitet, [...]
Daraus schließe ich, dass sqlCmd nichtblockierend arbeitet. Außerdem ist DbLog noch als asynchron (asyncMode = 1) konfiguriert.
Dennoch scheint es so, als ob sich manchmal die abgesetzten sqlCmds gegenseitig behindern (es werden für 24 Devices minütlich Werte gespeichert - da kommt es selten, aber offenbar manchmal vor, dass mehrere Befehle zeitlich dicht beieinander liegen):
2022.08.17 23:12:59 3: DbRep DBRep_Strom - Number of entries processed in db fhem: 1 by INSERT
2022.08.17 23:12:59 3: DbRep DBRep_Strom - Number of entries processed in db fhem: 1 by INSERT
2022.08.17 23:13:00 3: DbRep DBRep_Strom - WARNING - running process 124594 will be killed now to start a new operation
2022.08.17 23:13:00 1: DbRep DBRep_Strom -> BlockingCall DbRep_sqlCmd pid:124594 Timeout: process terminated
2022.08.17 23:13:00 2: DbRep DBRep_Strom - Database command aborted: "Timeout: process terminated"
2022.08.17 23:13:00 3: DbRep DBRep_Strom - Number of entries processed in db fhem: 1 by INSERT
Wie kann das sein bzw. wie kann ich verhindern, dass die Befehle sich gegenseitig blockieren? Und warum steht oben "
BlockingCall DbRep", wird das doch nicht nonblocking ausgeführt?
Danke!!!
Zitat
2022.08.17 23:13:00 3: DbRep DBRep_Strom - WARNING - running process 124594 will be killed now to start a new operation
DbRep arbeitet nichtblockierend. Programmtechnisch wird ein bereits laufender BlockingCall (ein paralleler Prozess der die DB managt) beendet, wenn man in ein und demselben DbRep Device eine neue Aktion startet. Das sagt diese Meldung.
Verhindern kann man es wenn man bewusst darauf achtet (geht natürlich nur manuell), verschiedene/mehrere DbRep-Devices verwendet bzw. eine Chain aufbaut wie im Wiki beschrieben: https://wiki.fhem.de/wiki/DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten#Abarbeitung_einer_sequentiellen_Befehlskette_mittels_non-blocking_sqlCmd-Kommandos
Zitat
Und warum steht oben "BlockingCall DbRep", wird das doch nicht nonblocking ausgeführt?
Es ist der Name der Standard FHEM Perl-Routine welche den Parallelprozess ausführt. Führt einen eigentlich "blockierenden Call" aus. Kann man sich so als Eselsbrücke merken.
Danke, das hilft mir weiter.
Ich versuche gerade mal, eine userExitFn nach dem Beispiel aufzusetzen. Erstmal habe ich nur
userExitFn CleanUpAfterDBCmd
Und folgende Funktion:
sub CleanUpAfterDBCmd {
my ($name,$reading,$value) = @_;
my $hash = $defs{$name};
my $readings = $hash->{READINGS};
my $DEBUG = 1;
if ($DEBUG == 1) {
foreach my $key (keys %{$readings}) {
my $value = ReadingsVal($name, $key, 'error');
Log 1, ("CleanUpAfterDBCmd: $key => $value");
}
}
}
Der Output im Log ist:
2022.08.18 15:23:01 1: CleanUpAfterDBCmd: state => running
D.h. im Zeitpunkt, in dem die ExitFn aufgerufen wird, scheinen die anderen Readings noch nicht befüllt zu sein. Ein
ReadingsVal($name, "SqlResultRow_1", '(nix)')
in der sub ergibt dementsprechend auch "(nix)".
Auch die Log-Ausgabe von DbRep kommt im Log erst an, nachdem die userExitFn gelaufen ist:
2022.08.18 15:22:55 1: CleanUpAfterDBCmd: state => running
2022.08.18 15:22:55 3: DbRep DBRep_Strom - Number of entries processed in db fhem: 1 by INSERT
Wie komme denn in der ExitFn an den Inhalt des Readings SqlResultRow_1 wie in dem von Dir verlinkten Wiki-Beispiel?
Die userExitFn wird für jedes erzeugte Reading ausgeführt.
Nach dem Start gibt es nur state und running.
Danach werden die Readings erst erzeugt wenn der parallele BlockingCall mit den Ergebnissen zurück kommt (asynchron).
Die erzeugten Readings sind abrufbar wenn state mit "done" erzeugt wurde.
Wie im Beispiel erreichst du den Inhalt von SqlResultRow_1 so in der sub CleanUpAfterDBCmd:
if($reading eq "state" && $value eq "done") {
$rc = ReadingsVal($name, "SqlResultRow_1", "");
.....
LG
Danke, nur wird CleanUpAfterDBCmd hier nur einmal aufgerufen, und das, wenn der state "running" ist. Einen Aufruf mit dem "done" state habe ich hier nicht.
Egal, ich stehle Dir zuviel Deiner Zeit und löse das anders. Danke nochmal.
Stell mal sqlResultFormat auf separated ein.