diff --git a/samsung_appliance/appliances/__init__.py b/samsung_appliance/appliances/__init__.py index 5a6864d..20657a9 100644 --- a/samsung_appliance/appliances/__init__.py +++ b/samsung_appliance/appliances/__init__.py @@ -15,6 +15,7 @@ from .oven import OVEN from .fridge import FRIDGE + DESCRIPTORS: dict[str, ApplianceDescriptor] = { DRYER.name: DRYER, OVEN.name: OVEN, diff --git a/samsung_appliance/bridge.py b/samsung_appliance/bridge.py index d7d66c8..43dec1a 100644 --- a/samsung_appliance/bridge.py +++ b/samsung_appliance/bridge.py @@ -409,6 +409,11 @@ class PushBridge: self.log.warning( "unreachable for %.0fs — forcing session reconnect", elapsed) self._force_close_in_flight = True + # Null the dying session's on_unreachable so its keepalive thread + # can't flip availability offline after the new session takes over. + ka = self.keepalive + if ka is not None: + ka.on_unreachable = None try: sess.close() except Exception as e: diff --git a/samsung_appliance/keepalive.py b/samsung_appliance/keepalive.py index 9e47ac3..11fe464 100644 --- a/samsung_appliance/keepalive.py +++ b/samsung_appliance/keepalive.py @@ -67,6 +67,8 @@ class KeepaliveTask: try: self.session.ping() ok = True + except ConnectionError as e: + if self.log: self.log.debug("ping: %s", e) except Exception as e: if self.log: self.log.warning("ping: %s", e) # Real half-open detection: ping sends can succeed against a diff --git a/samsung_appliance/poll_scheduler.py b/samsung_appliance/poll_scheduler.py index a18ab15..ff8e6ba 100644 --- a/samsung_appliance/poll_scheduler.py +++ b/samsung_appliance/poll_scheduler.py @@ -237,6 +237,11 @@ class PollScheduler: self.log.warning("poll %s timeout (cooldown %.0fs)", href, cooldown) return + except ConnectionError as e: + self._poll_error_count += 1 + self._record_rtt((time.monotonic() - t0) * 1000.0) + if self.log: self.log.debug("poll %s: %s", href, e) + return except Exception as e: self._poll_error_count += 1 self._record_rtt((time.monotonic() - t0) * 1000.0) @@ -274,6 +279,11 @@ class PollScheduler: self.log.warning("sweep %s timeout (cooldown %.0fs)", path, cooldown) return + except ConnectionError as e: + self._poll_error_count += 1 + self._record_rtt((time.monotonic() - t0) * 1000.0) + if self.log: self.log.debug("sweep %s: %s", path, e) + return except Exception as e: self._poll_error_count += 1 self._record_rtt((time.monotonic() - t0) * 1000.0) @@ -300,4 +310,4 @@ class PollScheduler: if self.log: elapsed_ms = (time.monotonic() - t0) * 1000.0 self.log.info("sweep complete (%d links, %.0fms)", - len(indexed), elapsed_ms) + len(indexed), elapsed_ms) \ No newline at end of file