FHEM-Code wird in 99_myUtils.pm nicht ausgeführt

Begonnen von Pi_01, 04 August 2020, 07:32:50

Vorheriges Thema - Nächstes Thema

Pi_01

Guten Morgen,
hier ein kleiner Auszug aus meiner 99_myUtils.pm:


...
...
fhem("set room=Rollos open");
fhem("set meineRep sqlCmd UPDATE current SET VALUE='Test' WHERE device='meinDevice'");
...
...


Die erste Codezeile (set room....) wird ausgeführt, die zweite Codezeile (set meineRep ...) wird NICHT ausgeführt, d.h. der Datenbankeintrag wird nicht aktualisiert. Warum?

Testweise habe ich den Code "set meineRep ..." in die FHEM-Befehlszeile eingegeben. Der Datenbankeintrag wurde dann auch tatsächlich aktualisiert, d.h. die Codezeile selbst passt.

Aber warum wird der Code nicht in PERL bzw. der 99_myUtils.pm ausgeführt?

Wzut

weil set room=Rollos open komisch ausschaut und mit einem Fehler beendet wird ?
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

Pi_01

Der Code fhem("set room=Rollos open"); bewirkt das alle Rollos im Raum "Rollos" geöffnet werden.

Das passiert auch tatsächlich. Ich kann hier keinen Fehler erkennen.

DS_Starter

Hast du in meineRep mal den verbose Level hochgezogen ? Dann sollte man sehen ob tatsächlich nichts angestartet wird oder vllt. doch ein Fehler gemeldet wird etc.
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Pi_01

Was hat eigentlich diese Fehlermeldung zu bedeuten:

2020.08.04 08:52:23 4: n_alle_Rollos_70 exec set room=alleRollos pct 70
2020.08.04 08:52:23 3: n_alle_Rollos_70 return value: Unknown argument pct, choose one of active execNow inactive modifyTimeSpec
Unknown argument pct, choose one of eraseReadings:noArg sumValue:display,writeToDB,writeToDBSingle,writeToDBInTime averageValue:display,writeToDB,writeToDBSingle,writeToDBInTime changeValue delDoublets:adviceDelete,delete delEntries delSeqDoublets:adviceRemain,adviceDelete,delete deviceRename readingRename exportToFile importFromFile maxValue:display,writeToDB,deleteOther minValue:display,writeToDB,deleteOther fetchrows:history,current diffValue:display,writeToDB index:list_all,recreate_Search_Idx,drop_Search_Idx,recreate_Report_Idx,drop_Report_Idx adminCredentials insert reduceLog sqlCmd:textField-long sqlSpecial:50mostFreqLogsLast2days,allDevCount,allDevReadCount,recentReadingsOfDevice,readingsDifferenceByTimeDelta syncStandby tableCurrentFillup:noArg tableCurrentPurge:noArg dumpMySQL:clientSide,serverSide optimizeTables:noArg restoreMySQL:  countEntries:history,current
Unknown argument pct, choose one of active execNow inactive modifyTimeSpec
Unknown argument pct, choose one of active execNow inactive modifyTimeSpec
Unknown argument pct, choose one of active:noArg addRegexpPart inactive:noArg removeRegexpPart
Unknown argument pct, choose one of active:noArg addRegexpPart inactive:noArg removeRegexpPart
Unknown argument pct, choose one of active:noArg addRegexpPart inactive:noArg removeRegexpPart
Unknown argument pct, choose one of active:noArg addRegexpPart inactive:noArg removeRegexpPart
Unknown argument pct, choose one of active:noArg addRegexpPart inactive:noArg removeRegexpPart


Anmerkung: trotz der Fehlermeldung werden die Rollos angesteuert.

Frank_Huber

Zitat von: Pi_01 am 04 August 2020, 08:56:49
Was hat eigentlich diese Fehlermeldung zu bedeuten:

Anmerkung: trotz der Fehlermeldung werden die Rollos angesteuert.
Du hast Dinge im Raum die kein pct als set Befehl können.
leg Dir für so Gruppierungen lieber ein Structure an. --> https://wiki.fhem.de/wiki/Structure

Pi_01

Danke Frank, war mir nicht bekannt.

Mein Code sieht jetzt wie folgt aus:


...
...
fhem("set structure_test_alle_rollos open");
fhem("set meineRep sqlCmd UPDATE current SET VALUE='Test' WHERE device='meinDevice'");
...
...


Dieser Code läuft ohne Fehler durch.

Anders sieht`s aus, wenn ich eine zweite SQL-Anweisung ausführen möchte:


...
...
fhem("set structure_test_alle_rollos open");
fhem("set meineRep sqlCmd UPDATE current SET VALUE='Test' WHERE device='meinDevice'");
fhem("set meineRep sqlCmd INSERT INTO history (DEVICE,TYPE,EVENT,READING,VALUE) ..........");
...
...


In diesem Fall wird mir in den Logs folgende Fehlermeldung zurückgeliefert:

2020.08.04 13:50:37 3: DbRep meineRep - WARNING - old process 13831 will be killed now to start a new BlockingCall
2020.08.04 13:50:37 1: DbRep meineRep -> BlockingCall  pid: Timeout: process terminated
2020.08.04 13:50:37 2: DbRep meineRep - Database command aborted due to "Timeout: process terminated"


Wo liegt der Fehler?

DS_Starter

Das hängt mit der asynchronen Arbeitsweise zusammen. Der erste Befehl läuft noch wenn du den zweiten losjagst. Entweder du benutzt ein weiteres DbRep oder die userExitFn im DbRep Device. Heute Abend kann ich dir mehr helfen falls Bedarf.
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Pi_01

Zitat von: DS_Starter am 04 August 2020, 14:35:42
Das hängt mit der asynchronen Arbeitsweise zusammen. Der erste Befehl läuft noch wenn du den zweiten losjagst.

So etwas hatte ich schon befürchtet, weshalb ich zwischen den zwei SQL-Anweisungen versuchsweise ein sleep(5); einbaute.
Aber selbst nach einer Wartezeit von 5 Sekunden kommt immer noch der gleiche Fehler zustande.
Interessant ist auch, dass bei mehreren Insert`s ....
fhem("set meineRep sqlCmd INSERT INTO history (DEVICE,TYPE,EVENT,READING,VALUE) value ('meinDevice1' ..........");
fhem("set meineRep sqlCmd INSERT INTO history (DEVICE,TYPE,EVENT,READING,VALUE) value ('meinDevice2' ..........");
fhem("set meineRep sqlCmd INSERT INTO history (DEVICE,TYPE,EVENT,READING,VALUE) value ('meinDevice3' ..........");


... nur das letzte SQL-Query ausgeführt wird (in der history-Tabelle findet man nur den Eintrag "meinDevice3").

Erwartet hätte ich eigentlich, dass das erste SQL-Query ausgeführt wird (meinDevice1), und der Rest nicht (weil der erste Befehl noch läuft ...)

Otto123

zeig das mal mit dem sleep, das wird nämlich gern völlig falsch verstanden :)

Aber das trägt sicher nicht zur Lösung bei, da kennt sich Heiko besser aus :)
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

DS_Starter

#10
Otto der alte Fuchs  :) ... aber in diesem Fall gibt es wirklich bessere Lösungen als ein sleep.

Also ...
ZitatInteressant ist auch, dass bei mehreren Insert`s .... ... nur das letzte SQL-Query ausgeführt wird (in der history-Tabelle findet man nur den Eintrag "meinDevice3").

Erwartet hätte ich eigentlich, dass das erste SQL-Query ausgeführt wird (meinDevice1), und der Rest nicht (weil der erste Befehl noch läuft ...)
Du hast ja gesehen, dass ein neuer SQL  Befehl einen vorherigen noch laufenden SQL killt. Es kommt die Meldung

2020.08.04 13:50:37 3: DbRep meineRep - WARNING - old process 13831 will be killed now to start a new BlockingCall

als Hinweis darauf. Nur der letzte SQL setzt sich durch.

Deswegen gibt es folgende Ansätze:

1. du verwendest für jedes Statement jeweils ein eigenes DbRep. Einfach durch "copy <old> <new>" erzeugen. Diese Devices kannst du gleichzeitig mit SQL Statements laufen lassen. Aber Achtung, techn. bedingt braucht die Methode viel Speicher. Die globale Variable blockingCallMax sollte in diesem Fall verwendet werden damit BlockingCalls ggf. serialisiert werden.

2. Du verwendest eine sogenannte "chain" unter Verwendung des Attributs userExitFn. Dabei werden die einzelnen SQLs nacheinander ausgeführt. Sobald ein Device mit der Abarbeitung fertig ist, startet es über eine aufgerufene Funktion in dem Attribut den Nachfolger an usw. bis die gesamte Kette fertig ist. Ich habe im Wiki ein Beispeil beschrieben.Den Level dieser Variante möchte ich schon als "advanced" bezeichnen.Der Vollständigkeit halber sei noch erwähnt dass du nach Ausführung einer DbRep Aktion im Attribut executeAfterProc ein FHEM-Kommando oder eine Perl-Funktion ausführen kannst.



Einfacher ist vermutlich die nächste Variante.

3. Du führst nur das Update mit einem DbRep aus. Die Inserts erledigst du nicht per SQL, sondern führst im DbLog-Device ein addCacheLine aus. Der Befehl stellt zunächst die Daten in den Cache und schreibt sie beim nächsten Sync zusammen mit den Logging Daten in die history. Voraussetzung ist dass dein DbLog im asynchronen Mode läuft !
Die Syntax findest du in der Comref. Mal grob skizziert könnte es nun so aussehen:
...
...
fhem("set structure_test_alle_rollos open");
fhem("set meineRep sqlCmd UPDATE current SET VALUE='Test' WHERE device='meinDevice'");
fhem("set DbLog addCacheLine YYYY-MM-DD HH:MM:SS|<device>|<type>|<event>|<reading>|<value>");
fhem("set DbLog addCacheLine YYYY-MM-DD HH:MM:SS|<device>|<type>|<event>|<reading>|<value>");
fhem("set DbLog addCacheLine YYYY-MM-DD HH:MM:SS|<device>|<type>|<event>|<reading>|<value>");
...
...


Grüße,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Pi_01

#11
Danke DS-Starter für deine Bemühungen!
Das Thema ist komplexer als ich dachte, ich wollte doch eigentlich nur ein paar Datenbank-Querys durchführen ...
Wenn ich mal wieder etwas mehr Zeit habe, muss ich mich tiefer mit dem Thema befassen.

Zitat von: Otto123 am 04 August 2020, 17:20:42
zeig das mal mit dem sleep, das wird nämlich gern völlig falsch verstanden :)

Auf was willst du konkret hinaus?
Wie wird ein Sleep richtig gesetzt?

Vorerst wäre ich mit so einem Workaround zufrieden, auch wenn es keine saubere Lösung darstellt.

Wenn ich ein Query absetze, 5 Sekunden warte, und dann erst das nächste Query absetze, dann sollte das erste Query doch schon längst durchgelaufen sein. 5 Sekunden ist eine Menge!

Otto123

zeig doch bitte deinen Code mit sleep, ich habe doch keine Ahnung wie Du es gemacht hast. Und ich wollte Dir konkret helfen und nicht erklären in welcher Sprache sleep wie verwendet wird.
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

DS_Starter

ZitatDas Thema ist komplexer als ich dachte, ich wollte doch eigentlich nur ein paar Datenbank-Querys durchführen ...
Naja, nicht unbedingt. Ich wollte dich nicht mit Varianten erschlagen. Deswegen kopiere dir dein DbRep nach zwei oder drei weitere.
Verwende in deinem Skript für jedes SQL ein anderes DbRep und fertig. Probiers einfach aus. Bei Bedarf kann man es dann ausbauen mit den Alternativen...
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Pi_01

Zitat von: DS_Starter am 04 August 2020, 22:02:44
Deswegen kopiere dir dein DbRep nach zwei oder drei weitere.
Verwende in deinem Skript für jedes SQL ein anderes DbRep und fertig. Probiers einfach aus.
Jetzt funktioniert es tadellos.
Nochmal recht herzlichen Dank für deine Bemühungen!!!