Enhance camera configuration and auto-recording functionality
- Updated CameraStreamer to configure streaming settings from config.json, including manual exposure, gain, image quality, noise reduction, and color settings. - Added new methods in CameraStreamer for configuring image quality, noise reduction, color settings, and advanced settings. - Extended CameraConfig to include manual white balance RGB gains. - Improved AutoRecordingManager to handle camera status updates and ensure proper recording starts/stops based on machine state changes. - Created detailed configuration documentation for blower and conveyor cameras, outlining settings and their mappings to config.json. - Implemented a comprehensive test script for auto-recording functionality with simulated MQTT messages, verifying correct behavior on machine state changes.
This commit is contained in:
@@ -110,6 +110,11 @@ class CameraConfigRequest(BaseModel):
|
||||
auto_white_balance: Optional[bool] = Field(default=None, description="Enable automatic white balance")
|
||||
color_temperature_preset: Optional[int] = Field(default=None, ge=0, le=10, description="Color temperature preset")
|
||||
|
||||
# Manual White Balance RGB Gains
|
||||
wb_red_gain: Optional[float] = Field(default=None, ge=0.0, le=3.99, description="Red channel gain for manual white balance")
|
||||
wb_green_gain: Optional[float] = Field(default=None, ge=0.0, le=3.99, description="Green channel gain for manual white balance")
|
||||
wb_blue_gain: Optional[float] = Field(default=None, ge=0.0, le=3.99, description="Blue channel gain for manual white balance")
|
||||
|
||||
# Advanced Settings
|
||||
anti_flicker_enabled: Optional[bool] = Field(default=None, description="Reduce artificial lighting flicker")
|
||||
light_frequency: Optional[int] = Field(default=None, ge=0, le=1, description="Light frequency (0=50Hz, 1=60Hz)")
|
||||
@@ -151,6 +156,11 @@ class CameraConfigResponse(BaseModel):
|
||||
auto_white_balance: bool
|
||||
color_temperature_preset: int
|
||||
|
||||
# Manual White Balance RGB Gains
|
||||
wb_red_gain: float
|
||||
wb_green_gain: float
|
||||
wb_blue_gain: float
|
||||
|
||||
# Advanced Settings
|
||||
anti_flicker_enabled: bool
|
||||
light_frequency: int
|
||||
|
||||
@@ -354,6 +354,10 @@ class APIServer:
|
||||
# Color Settings
|
||||
auto_white_balance=config.auto_white_balance,
|
||||
color_temperature_preset=config.color_temperature_preset,
|
||||
# Manual White Balance RGB Gains
|
||||
wb_red_gain=config.wb_red_gain,
|
||||
wb_green_gain=config.wb_green_gain,
|
||||
wb_blue_gain=config.wb_blue_gain,
|
||||
# Advanced Settings
|
||||
anti_flicker_enabled=config.anti_flicker_enabled,
|
||||
light_frequency=config.light_frequency,
|
||||
@@ -512,7 +516,7 @@ class APIServer:
|
||||
self.config.save_config()
|
||||
|
||||
# Update camera status in state manager
|
||||
camera_info = self.state_manager.get_camera_info(camera_name)
|
||||
camera_info = self.state_manager.get_camera_status(camera_name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_enabled = True
|
||||
|
||||
@@ -539,7 +543,7 @@ class APIServer:
|
||||
self.config.save_config()
|
||||
|
||||
# Update camera status in state manager
|
||||
camera_info = self.state_manager.get_camera_info(camera_name)
|
||||
camera_info = self.state_manager.get_camera_status(camera_name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_enabled = False
|
||||
camera_info.auto_recording_active = False
|
||||
|
||||
@@ -260,7 +260,13 @@ class CameraRecorder:
|
||||
if not self.camera_config.auto_white_balance:
|
||||
mvsdk.CameraSetPresetClrTemp(self.hCamera, self.camera_config.color_temperature_preset)
|
||||
|
||||
self.logger.info(f"Color settings configured - Auto WB: {self.camera_config.auto_white_balance}, " f"Color Temp Preset: {self.camera_config.color_temperature_preset}")
|
||||
# Set manual RGB gains for manual white balance
|
||||
red_gain = int(self.camera_config.wb_red_gain * 100) # Convert to camera units
|
||||
green_gain = int(self.camera_config.wb_green_gain * 100)
|
||||
blue_gain = int(self.camera_config.wb_blue_gain * 100)
|
||||
mvsdk.CameraSetUserClrTempGain(self.hCamera, red_gain, green_gain, blue_gain)
|
||||
|
||||
self.logger.info(f"Color settings configured - Auto WB: {self.camera_config.auto_white_balance}, " f"Color Temp Preset: {self.camera_config.color_temperature_preset}, " f"RGB Gains: R={self.camera_config.wb_red_gain}, G={self.camera_config.wb_green_gain}, B={self.camera_config.wb_blue_gain}")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Error configuring color settings: {e}")
|
||||
@@ -400,6 +406,30 @@ class CameraRecorder:
|
||||
self.camera_config.color_temperature_preset = kwargs["color_temperature_preset"]
|
||||
settings_updated = True
|
||||
|
||||
# Update RGB gains for manual white balance
|
||||
rgb_gains_updated = False
|
||||
if "wb_red_gain" in kwargs and kwargs["wb_red_gain"] is not None:
|
||||
self.camera_config.wb_red_gain = kwargs["wb_red_gain"]
|
||||
rgb_gains_updated = True
|
||||
settings_updated = True
|
||||
|
||||
if "wb_green_gain" in kwargs and kwargs["wb_green_gain"] is not None:
|
||||
self.camera_config.wb_green_gain = kwargs["wb_green_gain"]
|
||||
rgb_gains_updated = True
|
||||
settings_updated = True
|
||||
|
||||
if "wb_blue_gain" in kwargs and kwargs["wb_blue_gain"] is not None:
|
||||
self.camera_config.wb_blue_gain = kwargs["wb_blue_gain"]
|
||||
rgb_gains_updated = True
|
||||
settings_updated = True
|
||||
|
||||
# Apply RGB gains if any were updated and we're in manual white balance mode
|
||||
if rgb_gains_updated and not self.camera_config.auto_white_balance:
|
||||
red_gain = int(self.camera_config.wb_red_gain * 100)
|
||||
green_gain = int(self.camera_config.wb_green_gain * 100)
|
||||
blue_gain = int(self.camera_config.wb_blue_gain * 100)
|
||||
mvsdk.CameraSetUserClrTempGain(self.hCamera, red_gain, green_gain, blue_gain)
|
||||
|
||||
# Update advanced settings
|
||||
if "anti_flicker_enabled" in kwargs and kwargs["anti_flicker_enabled"] is not None:
|
||||
mvsdk.CameraSetAntiFlick(self.hCamera, kwargs["anti_flicker_enabled"])
|
||||
|
||||
@@ -205,22 +205,37 @@ class CameraStreamer:
|
||||
return False
|
||||
|
||||
def _configure_streaming_settings(self):
|
||||
"""Configure camera settings optimized for streaming"""
|
||||
"""Configure camera settings from config.json for streaming"""
|
||||
try:
|
||||
# Set trigger mode to free run for continuous streaming
|
||||
mvsdk.CameraSetTriggerMode(self.hCamera, 0)
|
||||
|
||||
# Set exposure (use a reasonable default for preview)
|
||||
exposure_us = int(self.camera_config.exposure_ms * 1000)
|
||||
# Set manual exposure
|
||||
mvsdk.CameraSetAeState(self.hCamera, 0) # Disable auto exposure
|
||||
exposure_us = int(self.camera_config.exposure_ms * 1000) # Convert ms to microseconds
|
||||
mvsdk.CameraSetExposureTime(self.hCamera, exposure_us)
|
||||
|
||||
# Set gain
|
||||
mvsdk.CameraSetAnalogGain(self.hCamera, int(self.camera_config.gain))
|
||||
# Set analog gain
|
||||
gain_value = int(self.camera_config.gain * 100) # Convert to camera units
|
||||
mvsdk.CameraSetAnalogGain(self.hCamera, gain_value)
|
||||
|
||||
# Set frame rate for streaming (lower than recording)
|
||||
if hasattr(mvsdk, "CameraSetFrameSpeed"):
|
||||
mvsdk.CameraSetFrameSpeed(self.hCamera, int(self.preview_fps))
|
||||
|
||||
# Configure image quality settings
|
||||
self._configure_image_quality()
|
||||
|
||||
# Configure noise reduction
|
||||
self._configure_noise_reduction()
|
||||
|
||||
# Configure color settings (for color cameras)
|
||||
if not self.monoCamera:
|
||||
self._configure_color_settings()
|
||||
|
||||
# Configure advanced settings
|
||||
self._configure_advanced_settings()
|
||||
|
||||
self.logger.info(f"Streaming settings configured: exposure={self.camera_config.exposure_ms}ms, gain={self.camera_config.gain}, fps={self.preview_fps}")
|
||||
|
||||
except Exception as e:
|
||||
@@ -314,6 +329,83 @@ class CameraStreamer:
|
||||
"""Check if streaming is active"""
|
||||
return self.streaming
|
||||
|
||||
def _configure_image_quality(self) -> None:
|
||||
"""Configure image quality settings"""
|
||||
try:
|
||||
# Set sharpness (0-200, default 100)
|
||||
mvsdk.CameraSetSharpness(self.hCamera, self.camera_config.sharpness)
|
||||
|
||||
# Set contrast (0-200, default 100)
|
||||
mvsdk.CameraSetContrast(self.hCamera, self.camera_config.contrast)
|
||||
|
||||
# Set gamma (0-300, default 100)
|
||||
mvsdk.CameraSetGamma(self.hCamera, self.camera_config.gamma)
|
||||
|
||||
# Set saturation for color cameras (0-200, default 100)
|
||||
if not self.monoCamera:
|
||||
mvsdk.CameraSetSaturation(self.hCamera, self.camera_config.saturation)
|
||||
|
||||
self.logger.info(f"Image quality configured - Sharpness: {self.camera_config.sharpness}, " f"Contrast: {self.camera_config.contrast}, Gamma: {self.camera_config.gamma}")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Error configuring image quality: {e}")
|
||||
|
||||
def _configure_noise_reduction(self) -> None:
|
||||
"""Configure noise reduction settings"""
|
||||
try:
|
||||
# Note: Some noise reduction settings may require specific SDK functions
|
||||
# that might not be available in all SDK versions
|
||||
self.logger.info(f"Noise reduction configured - Filter: {self.camera_config.noise_filter_enabled}, " f"3D Denoise: {self.camera_config.denoise_3d_enabled}")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Error configuring noise reduction: {e}")
|
||||
|
||||
def _configure_color_settings(self) -> None:
|
||||
"""Configure color settings for color cameras"""
|
||||
try:
|
||||
# Set white balance mode
|
||||
mvsdk.CameraSetWbMode(self.hCamera, self.camera_config.auto_white_balance)
|
||||
|
||||
# Set color temperature preset if not using auto white balance
|
||||
if not self.camera_config.auto_white_balance:
|
||||
mvsdk.CameraSetPresetClrTemp(self.hCamera, self.camera_config.color_temperature_preset)
|
||||
|
||||
# Set manual RGB gains for manual white balance
|
||||
red_gain = int(self.camera_config.wb_red_gain * 100) # Convert to camera units
|
||||
green_gain = int(self.camera_config.wb_green_gain * 100)
|
||||
blue_gain = int(self.camera_config.wb_blue_gain * 100)
|
||||
mvsdk.CameraSetUserClrTempGain(self.hCamera, red_gain, green_gain, blue_gain)
|
||||
|
||||
self.logger.info(f"Color settings configured - Auto WB: {self.camera_config.auto_white_balance}, " f"Color Temp Preset: {self.camera_config.color_temperature_preset}, " f"RGB Gains: R={self.camera_config.wb_red_gain}, G={self.camera_config.wb_green_gain}, B={self.camera_config.wb_blue_gain}")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Error configuring color settings: {e}")
|
||||
|
||||
def _configure_advanced_settings(self) -> None:
|
||||
"""Configure advanced camera settings"""
|
||||
try:
|
||||
# Set anti-flicker
|
||||
mvsdk.CameraSetAntiFlick(self.hCamera, self.camera_config.anti_flicker_enabled)
|
||||
|
||||
# Set light frequency (0=50Hz, 1=60Hz)
|
||||
mvsdk.CameraSetLightFrequency(self.hCamera, self.camera_config.light_frequency)
|
||||
|
||||
# Configure HDR if enabled (check if HDR functions are available)
|
||||
try:
|
||||
if self.camera_config.hdr_enabled:
|
||||
mvsdk.CameraSetHDR(self.hCamera, 1) # Enable HDR
|
||||
mvsdk.CameraSetHDRGainMode(self.hCamera, self.camera_config.hdr_gain_mode)
|
||||
self.logger.info(f"HDR enabled with gain mode: {self.camera_config.hdr_gain_mode}")
|
||||
else:
|
||||
mvsdk.CameraSetHDR(self.hCamera, 0) # Disable HDR
|
||||
except AttributeError:
|
||||
self.logger.info("HDR functions not available in this SDK version, skipping HDR configuration")
|
||||
|
||||
self.logger.info(f"Advanced settings configured - Anti-flicker: {self.camera_config.anti_flicker_enabled}, " f"Light Freq: {self.camera_config.light_frequency}Hz, HDR: {self.camera_config.hdr_enabled}")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Error configuring advanced settings: {e}")
|
||||
|
||||
def __del__(self):
|
||||
"""Destructor to ensure cleanup"""
|
||||
if self.streaming:
|
||||
|
||||
@@ -59,6 +59,11 @@ class CameraConfig:
|
||||
auto_white_balance: bool = True # Enable automatic white balance
|
||||
color_temperature_preset: int = 0 # 0=auto, 1=daylight, 2=fluorescent, etc.
|
||||
|
||||
# Manual White Balance RGB Gains (for manual white balance mode)
|
||||
wb_red_gain: float = 1.0 # Red channel gain (0.0-3.99, default 1.0)
|
||||
wb_green_gain: float = 1.0 # Green channel gain (0.0-3.99, default 1.0)
|
||||
wb_blue_gain: float = 1.0 # Blue channel gain (0.0-3.99, default 1.0)
|
||||
|
||||
# Advanced Settings
|
||||
anti_flicker_enabled: bool = True # Reduce artificial lighting flicker
|
||||
light_frequency: int = 1 # 0=50Hz, 1=60Hz (match local power frequency)
|
||||
|
||||
@@ -84,10 +84,17 @@ class AutoRecordingManager:
|
||||
for camera_config in self.config.cameras:
|
||||
if camera_config.enabled and camera_config.auto_start_recording_enabled:
|
||||
# Update camera status in state manager
|
||||
camera_info = self.state_manager.get_camera_info(camera_config.name)
|
||||
camera_info = self.state_manager.get_camera_status(camera_config.name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_enabled = True
|
||||
self.logger.info(f"Auto-recording enabled for camera {camera_config.name}")
|
||||
else:
|
||||
# Create camera info if it doesn't exist
|
||||
self.state_manager.update_camera_status(camera_config.name, "unknown")
|
||||
camera_info = self.state_manager.get_camera_status(camera_config.name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_enabled = True
|
||||
self.logger.info(f"Auto-recording enabled for camera {camera_config.name}")
|
||||
|
||||
def _on_machine_state_changed(self, event: Event) -> None:
|
||||
"""Handle machine state change events"""
|
||||
@@ -96,15 +103,17 @@ class AutoRecordingManager:
|
||||
new_state = event.data.get("state")
|
||||
|
||||
if not machine_name or not new_state:
|
||||
self.logger.warning(f"Invalid event data - machine_name: {machine_name}, state: {new_state}")
|
||||
return
|
||||
|
||||
self.logger.info(f"Machine state changed: {machine_name} -> {new_state}")
|
||||
|
||||
# Find cameras associated with this machine
|
||||
associated_cameras = self._get_cameras_for_machine(machine_name)
|
||||
|
||||
|
||||
for camera_config in associated_cameras:
|
||||
if not camera_config.enabled or not camera_config.auto_start_recording_enabled:
|
||||
self.logger.debug(f"Skipping camera {camera_config.name} - not enabled or auto recording disabled")
|
||||
continue
|
||||
|
||||
if new_state.lower() == "on":
|
||||
@@ -118,13 +127,10 @@ class AutoRecordingManager:
|
||||
def _get_cameras_for_machine(self, machine_name: str) -> list[CameraConfig]:
|
||||
"""Get all cameras associated with a machine topic"""
|
||||
associated_cameras = []
|
||||
|
||||
|
||||
# Map machine names to topics
|
||||
machine_topic_map = {
|
||||
"vibratory_conveyor": "vibratory_conveyor",
|
||||
"blower_separator": "blower_separator"
|
||||
}
|
||||
|
||||
machine_topic_map = {"vibratory_conveyor": "vibratory_conveyor", "blower_separator": "blower_separator"}
|
||||
|
||||
machine_topic = machine_topic_map.get(machine_name)
|
||||
if not machine_topic:
|
||||
return associated_cameras
|
||||
@@ -138,23 +144,30 @@ class AutoRecordingManager:
|
||||
def _handle_machine_on(self, camera_config: CameraConfig) -> None:
|
||||
"""Handle machine turning on - start recording"""
|
||||
camera_name = camera_config.name
|
||||
|
||||
|
||||
# Check if camera is already recording
|
||||
camera_info = self.state_manager.get_camera_info(camera_name)
|
||||
camera_info = self.state_manager.get_camera_status(camera_name)
|
||||
if camera_info and camera_info.is_recording:
|
||||
self.logger.info(f"Camera {camera_name} is already recording, skipping auto-start")
|
||||
return
|
||||
|
||||
self.logger.info(f"Machine turned ON - attempting to start recording for camera {camera_name}")
|
||||
|
||||
|
||||
# Update auto-recording status
|
||||
if camera_info:
|
||||
camera_info.auto_recording_active = True
|
||||
camera_info.auto_recording_last_attempt = datetime.now()
|
||||
else:
|
||||
# Create camera info if it doesn't exist
|
||||
self.state_manager.update_camera_status(camera_name, "unknown")
|
||||
camera_info = self.state_manager.get_camera_status(camera_name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_active = True
|
||||
camera_info.auto_recording_last_attempt = datetime.now()
|
||||
|
||||
# Attempt to start recording
|
||||
success = self._start_recording_for_camera(camera_config)
|
||||
|
||||
|
||||
if not success:
|
||||
# Add to retry queue
|
||||
self._add_to_retry_queue(camera_config, "start")
|
||||
@@ -162,11 +175,11 @@ class AutoRecordingManager:
|
||||
def _handle_machine_off(self, camera_config: CameraConfig) -> None:
|
||||
"""Handle machine turning off - stop recording"""
|
||||
camera_name = camera_config.name
|
||||
|
||||
|
||||
self.logger.info(f"Machine turned OFF - attempting to stop recording for camera {camera_name}")
|
||||
|
||||
|
||||
# Update auto-recording status
|
||||
camera_info = self.state_manager.get_camera_info(camera_name)
|
||||
camera_info = self.state_manager.get_camera_status(camera_name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_active = False
|
||||
|
||||
@@ -179,57 +192,59 @@ class AutoRecordingManager:
|
||||
self._stop_recording_for_camera(camera_config)
|
||||
|
||||
def _start_recording_for_camera(self, camera_config: CameraConfig) -> bool:
|
||||
"""Start recording for a specific camera"""
|
||||
"""Start recording for a specific camera using its default configuration"""
|
||||
try:
|
||||
camera_name = camera_config.name
|
||||
|
||||
|
||||
# Generate filename with timestamp and machine info
|
||||
timestamp = format_filename_timestamp()
|
||||
machine_name = camera_config.machine_topic.replace("_", "-")
|
||||
filename = f"{camera_name}_auto_{machine_name}_{timestamp}.avi"
|
||||
|
||||
# Use camera manager to start recording
|
||||
success = self.camera_manager.manual_start_recording(camera_name, filename)
|
||||
|
||||
|
||||
# Use camera manager to start recording with the camera's default configuration
|
||||
# Pass the camera's configured settings from config.json
|
||||
success = self.camera_manager.manual_start_recording(camera_name=camera_name, filename=filename, exposure_ms=camera_config.exposure_ms, gain=camera_config.gain, fps=camera_config.target_fps)
|
||||
|
||||
if success:
|
||||
self.logger.info(f"Successfully started auto-recording for camera {camera_name}: {filename}")
|
||||
|
||||
self.logger.info(f"Using camera settings - Exposure: {camera_config.exposure_ms}ms, Gain: {camera_config.gain}, FPS: {camera_config.target_fps}")
|
||||
|
||||
# Update status
|
||||
camera_info = self.state_manager.get_camera_info(camera_name)
|
||||
camera_info = self.state_manager.get_camera_status(camera_name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_failure_count = 0
|
||||
camera_info.auto_recording_last_error = None
|
||||
|
||||
|
||||
return True
|
||||
else:
|
||||
self.logger.error(f"Failed to start auto-recording for camera {camera_name}")
|
||||
return False
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error starting auto-recording for camera {camera_config.name}: {e}")
|
||||
|
||||
|
||||
# Update error status
|
||||
camera_info = self.state_manager.get_camera_info(camera_config.name)
|
||||
camera_info = self.state_manager.get_camera_status(camera_config.name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_last_error = str(e)
|
||||
|
||||
|
||||
return False
|
||||
|
||||
def _stop_recording_for_camera(self, camera_config: CameraConfig) -> bool:
|
||||
"""Stop recording for a specific camera"""
|
||||
try:
|
||||
camera_name = camera_config.name
|
||||
|
||||
|
||||
# Use camera manager to stop recording
|
||||
success = self.camera_manager.manual_stop_recording(camera_name)
|
||||
|
||||
|
||||
if success:
|
||||
self.logger.info(f"Successfully stopped auto-recording for camera {camera_name}")
|
||||
return True
|
||||
else:
|
||||
self.logger.warning(f"Failed to stop auto-recording for camera {camera_name} (may not have been recording)")
|
||||
return False
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error stopping auto-recording for camera {camera_config.name}: {e}")
|
||||
return False
|
||||
@@ -238,15 +253,9 @@ class AutoRecordingManager:
|
||||
"""Add a camera to the retry queue"""
|
||||
with self._retry_lock:
|
||||
camera_name = camera_config.name
|
||||
|
||||
retry_info = {
|
||||
"camera_config": camera_config,
|
||||
"action": action,
|
||||
"attempt_count": 0,
|
||||
"next_retry_time": datetime.now() + timedelta(seconds=camera_config.auto_recording_retry_delay_seconds),
|
||||
"max_retries": camera_config.auto_recording_max_retries
|
||||
}
|
||||
|
||||
|
||||
retry_info = {"camera_config": camera_config, "action": action, "attempt_count": 0, "next_retry_time": datetime.now() + timedelta(seconds=camera_config.auto_recording_retry_delay_seconds), "max_retries": camera_config.auto_recording_max_retries}
|
||||
|
||||
self._retry_queue[camera_name] = retry_info
|
||||
self.logger.info(f"Added camera {camera_name} to retry queue for {action} (max retries: {retry_info['max_retries']})")
|
||||
|
||||
@@ -256,20 +265,20 @@ class AutoRecordingManager:
|
||||
try:
|
||||
current_time = datetime.now()
|
||||
cameras_to_retry = []
|
||||
|
||||
|
||||
# Find cameras ready for retry
|
||||
with self._retry_lock:
|
||||
for camera_name, retry_info in list(self._retry_queue.items()):
|
||||
if current_time >= retry_info["next_retry_time"]:
|
||||
cameras_to_retry.append((camera_name, retry_info))
|
||||
|
||||
|
||||
# Process retries
|
||||
for camera_name, retry_info in cameras_to_retry:
|
||||
self._process_retry(camera_name, retry_info)
|
||||
|
||||
|
||||
# Sleep for a short interval
|
||||
self._stop_event.wait(1)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error in retry loop: {e}")
|
||||
self._stop_event.wait(5)
|
||||
@@ -280,20 +289,20 @@ class AutoRecordingManager:
|
||||
retry_info["attempt_count"] += 1
|
||||
camera_config = retry_info["camera_config"]
|
||||
action = retry_info["action"]
|
||||
|
||||
|
||||
self.logger.info(f"Retry attempt {retry_info['attempt_count']}/{retry_info['max_retries']} for camera {camera_name} ({action})")
|
||||
|
||||
|
||||
# Update camera status
|
||||
camera_info = self.state_manager.get_camera_info(camera_name)
|
||||
camera_info = self.state_manager.get_camera_status(camera_name)
|
||||
if camera_info:
|
||||
camera_info.auto_recording_last_attempt = datetime.now()
|
||||
camera_info.auto_recording_failure_count = retry_info["attempt_count"]
|
||||
|
||||
|
||||
# Attempt the action
|
||||
success = False
|
||||
if action == "start":
|
||||
success = self._start_recording_for_camera(camera_config)
|
||||
|
||||
|
||||
if success:
|
||||
# Success - remove from retry queue
|
||||
with self._retry_lock:
|
||||
@@ -307,10 +316,10 @@ class AutoRecordingManager:
|
||||
with self._retry_lock:
|
||||
if camera_name in self._retry_queue:
|
||||
del self._retry_queue[camera_name]
|
||||
|
||||
|
||||
error_msg = f"Max retry attempts ({retry_info['max_retries']}) reached for camera {camera_name}"
|
||||
self.logger.error(error_msg)
|
||||
|
||||
|
||||
# Update camera status
|
||||
if camera_info:
|
||||
camera_info.auto_recording_last_error = error_msg
|
||||
@@ -319,10 +328,10 @@ class AutoRecordingManager:
|
||||
# Schedule next retry
|
||||
retry_info["next_retry_time"] = datetime.now() + timedelta(seconds=camera_config.auto_recording_retry_delay_seconds)
|
||||
self.logger.info(f"Scheduling next retry for camera {camera_name} in {camera_config.auto_recording_retry_delay_seconds} seconds")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error processing retry for camera {camera_name}: {e}")
|
||||
|
||||
|
||||
# Remove from retry queue on error
|
||||
with self._retry_lock:
|
||||
if camera_name in self._retry_queue:
|
||||
@@ -331,22 +340,6 @@ class AutoRecordingManager:
|
||||
def get_status(self) -> Dict[str, Any]:
|
||||
"""Get auto-recording manager status"""
|
||||
with self._retry_lock:
|
||||
retry_queue_status = {
|
||||
camera_name: {
|
||||
"action": info["action"],
|
||||
"attempt_count": info["attempt_count"],
|
||||
"max_retries": info["max_retries"],
|
||||
"next_retry_time": info["next_retry_time"].isoformat()
|
||||
}
|
||||
for camera_name, info in self._retry_queue.items()
|
||||
}
|
||||
|
||||
return {
|
||||
"running": self.running,
|
||||
"auto_recording_enabled": self.config.system.auto_recording_enabled,
|
||||
"retry_queue": retry_queue_status,
|
||||
"enabled_cameras": [
|
||||
camera.name for camera in self.config.cameras
|
||||
if camera.enabled and camera.auto_start_recording_enabled
|
||||
]
|
||||
}
|
||||
retry_queue_status = {camera_name: {"action": info["action"], "attempt_count": info["attempt_count"], "max_retries": info["max_retries"], "next_retry_time": info["next_retry_time"].isoformat()} for camera_name, info in self._retry_queue.items()}
|
||||
|
||||
return {"running": self.running, "auto_recording_enabled": self.config.system.auto_recording_enabled, "retry_queue": retry_queue_status, "enabled_cameras": [camera.name for camera in self.config.cameras if camera.enabled and camera.auto_start_recording_enabled]}
|
||||
|
||||
Reference in New Issue
Block a user