FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: ToM_ToM am 06 Januar 2018, 18:01:32

Titel: Deep recursion on subroutine "main::readingsSingleUpdate"
Beitrag von: ToM_ToM am 06 Januar 2018, 18:01:32
Hallo Zusammen,

ich sehe den Wald vor lauter Bäumen nicht. Bin schon den ganzen Tag auf Fehlersuche, aber verstehe nicht wo hier eine Rekursion sein soll. Mein Fhem hängt sich leider mit folgendem UserReading auf.


EnergyToday:2.ENERGY_COUNTER:.* {
my $power = ReadingsVal("$NAME", "2.POWER", 0);
my @PowerMaxAll = split('\|', ReadingsVal("RepDB_Solarstrom", "POWER_MAX_ALL", "0|0"));
if($power > $PowerMaxAll[0]) {
fhem('set RepDB_Solarstrom sqlCmd SELECT \'POWER_MAX_ALL\' AS \'MaxPower\', VALUE, TIMESTAMP FROM history WHERE DEVICE = \'HM_GN_Solarstrom\' AND READING = \'2.POWER\' AND VALUE = (SELECT MAX(CONVERT(VALUE, DECIMAL(15,5))) FROM history WHERE DEVICE = \'HM_GN_Solarstrom\' AND READING = \'2.POWER\');');


my $energyTotal = ReadingsVal("$NAME", "2.ENERGY_COUNTER", 0);
my $energyTotalToday = ReadingsVal("$NAME", "EnergyTotalToday", 0);
my $energyToday = $energyTotal - $energyTotalToday;
my @EnergyMaxAll = split('\|', ReadingsVal("RepDB_Solarstrom", "ENERGY_MAX_DAY_ALL", "0|0"));
if($energyToday > $EnergyMaxAll[0]) {
fhem('set RepDB_Solarstrom sqlCmd SELECT \'ENERGY_MAX_DAY_ALL\' AS \'MaxEnergy\', VALUE, TIMESTAMP FROM history WHERE DEVICE = \'HM_GN_Solarstrom\' AND READING = \'EnergyToday\' AND VALUE = (SELECT MAX(CONVERT(VALUE, DECIMAL(15,5))) FROM history WHERE DEVICE = \'HM_GN_Solarstrom\' AND READING = \'EnergyToday\');');

my $localtime = (strftime("%Y-%m-%d %H:%M:%S",localtime()));
my $time = ReadingsTimestamp("$NAME", "2.ENERGY_COUNTER", 0);
fhem("setreading $NAME LastTelegramMessageSent $time");


return $energyToday;
}



Hier noch mein RepDB:


defmod RepDB_Solarstrom DbRep logdb
attr RepDB_Solarstrom device HM_GN_Solarstrom
attr RepDB_Solarstrom group Solar
attr RepDB_Solarstrom reading 2.POWER
attr RepDB_Solarstrom room Garten
attr RepDB_Solarstrom sqlResultFormat separated
attr RepDB_Solarstrom userReadings POWER_MAX_ALL:SqlResultRow_1.* { \
my $sqlResult = ReadingsVal("$NAME", "SqlResultRow_1", "");; \
if ($sqlResult =~ m/POWER_MAX_ALL\|(.*)/i ) { \
return $1;; \
} \
},\
\
ENERGY_MAX_DAY_ALL:SqlResultRow_1.* { \
my $sqlResult = ReadingsVal("$NAME", "SqlResultRow_1", "");; \
if ($sqlResult =~ m/ENERGY_MAX_DAY_ALL\|(.*)/i ) { \
return $1;; \
} \
}




Im LOG taucht folgendes auf:


2018.01.06 17:41:04 1: PERL WARNING: Deep recursion on subroutine "main::readingsSingleUpdate" at fhem.pl line 2245.
2018.01.06 17:41:04 3: eval: {
my $power = ReadingsVal("$NAME", "2.POWER", 0);
my @PowerMaxAll = split('\|', ReadingsVal("RepDB_Solarstrom", "POWER_MAX_ALL", "0|0"));
if($power > $PowerMaxAll[0]) {
fhem('set RepDB_Solarstrom sqlCmd SELECT \'POWER_MAX_ALL\' AS \'MaxPower\', VALUE, TIMESTAMP FROM history WHERE DEVICE = \'HM_GN_Solarstrom\' AND READING = \'2.POWER\' AND VALUE = (SELECT MAX(CONVERT(VALUE, DECIMAL(15,5))) FROM history WHERE DEVICE = \'HM_GN_Solarstrom\' AND READING = \'2.POWER\');');


my $energyTotal = ReadingsVal("$NAME", "2.ENERGY_COUNTER", 0);
my $energyTotalToday = ReadingsVal("$NAME", "EnergyTotalToday", 0);
my $energyToday = $energyTotal - $energyTotalToday;
my @EnergyMaxAll = split('\|', ReadingsVal("RepDB_Solarstrom", "ENERGY_MAX_DAY_ALL", "0|0"));
if($energyToday > $EnergyMaxAll[0]) {
fhem('set RepDB_Solarstrom sqlCmd SELECT \'ENERGY_MAX_DAY_ALL\' AS \'MaxEnergy\', VALUE, TIMESTAMP FROM history WHERE DEVICE = \'HM_GN_Solarstrom\' AND READING = \'EnergyToday\' AND VALUE = (SELECT MAX(CONVERT(VALUE, DECIMAL(15,5))) FROM history WHERE DEVICE = \'HM_GN_Solarstrom\' AND READING = \'EnergyToday\');');

my $localtime = (strftime("%Y-%m-%d %H:%M:%S",localtime()));
my $time = ReadingsTimestamp("$NAME", "2.ENERGY_COUNTER", 0);
fhem("setreading $NAME LastTelegramMessageSent $time");


return $energyToday;
}
2018.01.06 17:41:04 3: DbRep RepDB_Solarstrom - WARNING - old process 5190 will be killed now to start a new BlockingCall
2018.01.06 17:41:04 1: DbRep RepDB_Solarstrom -> BlockingCall sqlCmd_DoParse pid:5190 Timeout: process terminated
2018.01.06 17:41:04 3: DbRep RepDB_Solarstrom - WARNING - old process 5191 will be killed now to start a new BlockingCall
2018.01.06 17:41:04 1: DbRep RepDB_Solarstrom -> BlockingCall sqlCmd_DoParse pid:5191 Timeout: process terminated
2018.01.06 17:41:04 3: DbRep RepDB_Solarstrom - WARNING - old process 5192 will be killed now to start a new BlockingCall
2018.01.06 17:41:04 1: DbRep RepDB_Solarstrom -> BlockingCall sqlCmd_DoParse pid:5192 Timeout: process terminated
2018.01.06 17:41:04 3: DbRep RepDB_Solarstrom - WARNING - old process 5193 will be killed now to start a new BlockingCall
2018.01.06 17:41:04 1: DbRep RepDB_Solarstrom -> BlockingCall sqlCmd_DoParse pid:5193 Timeout: process terminated
2018.01.06 17:41:04 3: DbRep RepDB_Solarstrom - WARNING - old process 5194 will be killed now to start a new BlockingCall
2018.01.06 17:41:04 1: DbRep RepDB_Solarstrom -> BlockingCall sqlCmd_DoParse pid:5194 Timeout: process terminated
...


Ich hoffe, ihr habt eine Idee.

VG, Thomas
Titel: Antw:Deep recursion on subroutine "main::readingsSingleUpdate"
Beitrag von: KernSani am 06 Januar 2018, 18:49:13
Ich vermute, dass FHEM es nicht mag, wenn du innerhalb eines userreadings ein set auf das gleiche Device machst, was widerum die Erstellung eines userreadings zur Folge hätte etc...
Titel: Antw:Deep recursion on subroutine "main::readingsSingleUpdate"
Beitrag von: ToM_ToM am 06 Januar 2018, 18:54:40
ZitatIch vermute, dass FHEM es nicht mag, wenn du innerhalb eines userreadings ein set auf das gleiche Device machst, was widerum die Erstellung eines userreadings zur Folge hätte etc...

Selbst wenn ich dieses weglasse, hängt es sich mit dem gleichen Fehler auf.

fhem("setreading $NAME LastTelegramMessageSent $time");

Irgendwie merkwürdig.
Titel: Antw:Deep recursion on subroutine "main::readingsSingleUpdate"
Beitrag von: herrmannj am 06 Januar 2018, 19:07:17
Kann man so auch nicht beantworten.

Wenn Du am Anfang ein Log3 oder print einbaust wirst aber sehen _das_ es so ist. Um es einzugrenzen muss man den gesamten Verlauf event - trigger - set etc kennen.

Schau Dir an ob das userReading wirklich bei jeder Aktualisierung ( jetzt EnergyToday:2.ENERGY_COUNTER:.* ) erzeugt werden muss. Wenn nein, setze ein spezifischere Regex und verhindere damit die Rekursion.
Titel: Antw:Deep recursion on subroutine "main::readingsSingleUpdate"
Beitrag von: ToM_ToM am 06 Januar 2018, 19:39:03
Vielen Dank für eure Antworten. Ich habe es jetzt alles nochmal komplett umgebaut. Da nun mehrere Devices betroffen sind, denke ich, ist es wenig sinnvoll wenn ich den Code von den ganzen Definitionen hier poste, da wahrscheinlich niemand die gleiche Komplexität mit der gleichen Struktur haben wird.

VG, Thomas
Titel: Aw: Deep recursion on subroutine "main::readingsSingleUpdate"
Beitrag von: Torxgewinde am 31 August 2023, 19:32:26
Reduziert auf ein minimales Beispiel kann man den Fehler nachvollziehen:

defmod Blatest dummy
attr Blatest readingList wert
attr Blatest setList wert
attr Blatest userReadings meinUserReading:wert.* {\
    my $hash = $defs{$NAME};;\
    readingsBeginUpdate($hash);;\
    readingsEndUpdate($hash, 0);;\
    \
    return "fertig";\
}

setstate Blatest 2023-08-31 19:21:40 wert 123

Das Log besagt dann:
2023.08.31 18:13:31 1: PERL WARNING: Deep recursion on subroutine "main::readingsEndUpdate" at (eval 6273741) line 4.
2023.08.31 18:13:31 3: eval: {
 my $hash = $defs{$NAME};
 readingsBeginUpdate($hash);
 readingsEndUpdate($hash, 0);
 
 return "fertig";
}

Workaround, um aus einem Userreading ein anderes, eigenes Reading zu setzen ist dann zeitversetzt einen FHEM-Befehl abzusetzen:
defmod Blatest dummy
attr Blatest readingList wert
attr Blatest setList wert
attr Blatest userReadings meinUserReading:wert.* {\
fhem("sleep 0.1;; setreading $name noch_Ein_Reading 456");;\
\
return "fertig";;\
}

Frage: Geht das nicht doch ohne umständliche Zeitversetzung aus einem userReading heraus?