2026.02.22 11:35:24 1: 192.168.0.143:1002 disconnected, waiting to reappear (JeeLinker)
2026.02.22 11:35:24 1: DevIo JeeLinker JustClosed
2026.02.22 11:35:24 1: DevIO JeeLinker NEXT_OPEN:
2026.02.22 11:35:24 1: 192.168.0.143:1002 disconnected, waiting to reappear (JeeLinker)FHEM blockt auch mit dieser DevIo.pmZitatProblem: FHEM 100% CPU bei JeeLink über TCP (ser2net), sobald der Port kurz weg ist
Setup: JeeLink in FHEM als host:port (z.B. 192.168.0.143:1002), serielle Seite auf einer entfernten VM via ser2net.
Sobald der ser2net-Dienst kurz nicht verfügbar ist (Restart/Port weg), läuft FHEM in eine Schleife mit 100% CPU.
Symptom im Log (typisch):
- ... disconnected, waiting to reappear (JeeLinker)
- Stacktrace zeigt Pfad über DevIo_Disconnected / DevIo_SimpleRead und anschließend JeeLink_Ready → DevIo_OpenDev ...
Ursache (Root Cause)
Busy-Loop über %readyfnlist
Wenn das IODevice "disconnected" ist, landet es in FHEM in der readyfnlist. Dann ruft der Mainloop extrem häufig JeeLink_Ready() auf.
Wenn JeeLink_Ready() bei STATE=disconnected sofort wieder DevIo_OpenDev() startet (oder auch nur stumpf return 0 macht, aber im readyfnlist-Spin bleibt), kann FHEM praktisch ohne Schlaf laufen → 100% CPU.
Lösung/Änderungen
A) Reconnect throttlen ist nötig, aber allein nicht genug
Ein simples reopenDelay (z.B. 10s) in JeeLink_Ready() verhindert zwar den "Connect-Hammer", aber FHEM kann trotzdem 100% CPU ziehen, weil es während der Wartezeit weiter im readyfnlist-Spin steckt.
B) Finaler Fix: raus aus readyfnlist + Timer-basiertes ReopenErgebnis: Während reopenDelay ist FHEM nicht mehr "hot", CPU bleibt normal.
- Implementiert in 36_JeeLink.pm:
- neues Attribut: reopenDelay (Sekunden, Default 5)
- bei STATE=disconnected:
- aus %readyfnlist entfernen
- Reconnect über InternalTimer(now+reopenDelay, "JeeLink_Reopen", ...) planen
- neue Funktion JeeLink_Reopen() ruft dann einmal DevIo_OpenDev() auf
- nach erfolgreichem Reconnect (JeeLink_DoInit):
- Timer entfernen (RemoveInternalTimer)
- Backoff/Next-Open löschen
Ergebnis nach Fix
Kein 100%-CPU-Loop mehr bei ser2net restart
Reconnect-Versuche nur noch alle reopenDelay Sekunden
Reconnect blockiert nicht mehr ewig, wenn timeout reduziert wird
System bleibt während Ausfall stabil/bedienbar
--- a/FHEM/36_JeeLink.pm
+++ b/FHEM/36_JeeLink.pm
@@ -1,6 +1,7 @@
#!/usr/bin/perl
use strict;
use warnings;
+use Time::HiRes qw(gettimeofday);
@@
sub JeeLink_Initialize($)
{
my ($hash) = @_;
@@
- $hash->{AttrList} = "do_not_notify:1,0 dummy:1,0 showtime:1,0 "
+ $hash->{AttrList} = "do_not_notify:1,0 dummy:1,0 showtime:1,0 "
." initCommands"
." flashCommand"
." timeout"
+ ." reopenDelay"
." DebounceTime BeepLong BeepShort BeepDelay"
." tune " . join(" ", map { "tune_$_" } keys %RxListJeeLink)
." $readingFnAttributes";
}
@@
sub JeeLink_DoInit($)
{
my ($hash) = @_;
@@
JeeLink_Clear($hash);
readingsSingleUpdate($hash, "state", "opened", 1);
+ delete($hash->{NEXT_OPEN});
+ RemoveInternalTimer($hash, "JeeLink_Reopen");
# Reset the counter
delete($hash->{XMIT_TIME});
@@
}
@@
sub JeeLink_Ready($)
{
my ($hash) = @_;
- return DevIo_OpenDev($hash, 1, "JeeLink_DoInit")
- if($hash->{STATE} eq "disconnected");
+ if($hash->{STATE} eq "disconnected") {
+ my $name = $hash->{NAME};
+ my $delay = AttrVal($name, "reopenDelay", 5);
+ $delay = 5 if(!defined($delay) || $delay !~ /^\d+(?:\.\d+)?$/ || $delay < 0.1);
+
+ my $now = gettimeofday();
+ my $next = $hash->{NEXT_OPEN} // 0;
+ $next = $now + $delay if($next <= $now);
+ $hash->{NEXT_OPEN} = $next;
+
+ # IMPORTANT: avoid busy loop in %readyfnlist.
+ # Remove from readyfnlist and schedule a timer-based reopen attempt.
+ delete($readyfnlist{$name});
+ RemoveInternalTimer($hash, "JeeLink_Reopen");
+ InternalTimer($next, "JeeLink_Reopen", $hash, 0);
+
+ return 0;
+ }
# This is relevant for windows/USB only
my $po = $hash->{USBDev};
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags);
if($po) {
($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
}
return ($InBytes && $InBytes>0);
}
+sub JeeLink_Reopen($)
+{
+ my ($hash) = @_;
+ return if(!$hash || !defined($hash->{NAME}));
+ return if($hash->{STATE} ne "disconnected");
+ DevIo_OpenDev($hash, 1, "JeeLink_DoInit");
+}
defmod di_ReadingsWatcher DOIF ([ReadingsWatcher:dead] > 0) (msg Störung: [ReadingsWatcher:deadDevs])\
DOELSE()
attr di_ReadingsWatcher DbLogExclude .*
attr di_ReadingsWatcher do always
attr di_ReadingsWatcher repeatcmd 3600
attr di_ReadingsWatcher repeatsame 10
attr di_ReadingsWatcher room DOIF
attr di_ReadingsWatcher verbose 2
attr di_ReadingsWatcher wait 10
Zitatpassibe (DANKE!) hatte mir gestern noch souffliert:Waere das nicht ein Grund das Thema dahin zu verschieben, wo auch andere mitreden koennen?
ZitatTeilweise muss man sehr komplexe Programmierarbeit leisten, um mit FHEM solch einen Standard-Anwendungsfall abzudecken.
attr xyz 3600,,temperaturehinzugefügt.rw_ReadingsWatcher:deadDevs reagieren zB mittels(msg push @rr_Stefan Dead Devices: [rw_ReadingsWatcher:deadDevs]