implement status caching to reduce message volume

This commit is contained in:
Josh Hawkins 2025-12-15 14:04:38 -06:00
parent b2b884c5a6
commit 58d8ce9249

View File

@ -226,6 +226,31 @@ class CameraWatchdog(threading.Thread):
self._stall_timestamps: deque[float] = deque() self._stall_timestamps: deque[float] = deque()
self._stall_active: bool = False self._stall_active: bool = False
# Status caching to reduce message volume
self._last_detect_status: str | None = None
self._last_record_status: str | None = None
self._last_status_update_time: float = 0.0
def _send_detect_status(self, status: str, now: float) -> None:
"""Send detect status only if changed or retry_interval has elapsed."""
if (
status != self._last_detect_status
or (now - self._last_status_update_time) >= self.sleeptime
):
self.requestor.send_data(f"{self.config.name}/status/detect", status)
self._last_detect_status = status
self._last_status_update_time = now
def _send_record_status(self, status: str, now: float) -> None:
"""Send record status only if changed or retry_interval has elapsed."""
if (
status != self._last_record_status
or (now - self._last_status_update_time) >= self.sleeptime
):
self.requestor.send_data(f"{self.config.name}/status/record", status)
self._last_record_status = status
self._last_status_update_time = now
def _update_enabled_state(self) -> bool: def _update_enabled_state(self) -> bool:
"""Fetch the latest config and update enabled state.""" """Fetch the latest config and update enabled state."""
self.config_subscriber.check_for_updates() self.config_subscriber.check_for_updates()
@ -301,12 +326,9 @@ class CameraWatchdog(threading.Thread):
self.stop_all_ffmpeg() self.stop_all_ffmpeg()
# update camera status # update camera status
self.requestor.send_data( now = datetime.now().timestamp()
f"{self.config.name}/status/detect", "disabled" self._send_detect_status("disabled", now)
) self._send_record_status("disabled", now)
self.requestor.send_data(
f"{self.config.name}/status/record", "disabled"
)
self.was_enabled = enabled self.was_enabled = enabled
continue continue
@ -350,7 +372,7 @@ class CameraWatchdog(threading.Thread):
can_restart = time_since_last_restart >= self.sleeptime can_restart = time_since_last_restart >= self.sleeptime
if not self.capture_thread.is_alive(): if not self.capture_thread.is_alive():
self.requestor.send_data(f"{self.config.name}/status/detect", "offline") self._send_detect_status("offline", now)
self.camera_fps.value = 0 self.camera_fps.value = 0
self.logger.error( self.logger.error(
f"Ffmpeg process crashed unexpectedly for {self.config.name}." f"Ffmpeg process crashed unexpectedly for {self.config.name}."
@ -362,9 +384,7 @@ class CameraWatchdog(threading.Thread):
self.fps_overflow_count += 1 self.fps_overflow_count += 1
if self.fps_overflow_count == 3: if self.fps_overflow_count == 3:
self.requestor.send_data( self._send_detect_status("offline", now)
f"{self.config.name}/status/detect", "offline"
)
self.fps_overflow_count = 0 self.fps_overflow_count = 0
self.camera_fps.value = 0 self.camera_fps.value = 0
self.logger.info( self.logger.info(
@ -374,7 +394,7 @@ class CameraWatchdog(threading.Thread):
self.reset_capture_thread(drain_output=False) self.reset_capture_thread(drain_output=False)
last_restart_time = now last_restart_time = now
elif now - self.capture_thread.current_frame.value > 20: elif now - self.capture_thread.current_frame.value > 20:
self.requestor.send_data(f"{self.config.name}/status/detect", "offline") self._send_detect_status("offline", now)
self.camera_fps.value = 0 self.camera_fps.value = 0
self.logger.info( self.logger.info(
f"No frames received from {self.config.name} in 20 seconds. Exiting ffmpeg..." f"No frames received from {self.config.name} in 20 seconds. Exiting ffmpeg..."
@ -384,7 +404,7 @@ class CameraWatchdog(threading.Thread):
last_restart_time = now last_restart_time = now
else: else:
# process is running normally # process is running normally
self.requestor.send_data(f"{self.config.name}/status/detect", "online") self._send_detect_status("online", now)
self.fps_overflow_count = 0 self.fps_overflow_count = 0
for p in self.ffmpeg_other_processes: for p in self.ffmpeg_other_processes:
@ -455,9 +475,7 @@ class CameraWatchdog(threading.Thread):
continue continue
else: else:
self.requestor.send_data( self._send_record_status("online", now)
f"{self.config.name}/status/record", "online"
)
p["latest_segment_time"] = self.latest_cache_segment_time p["latest_segment_time"] = self.latest_cache_segment_time
if poll is None: if poll is None: