Enhance camera management features: add debug endpoint for camera manager state, implement live camera routes without authentication, and improve logging for camera initialization and status checks. Update Docker configuration to include environment variables for the web app.
This commit is contained in:
@@ -688,6 +688,29 @@ class APIServer:
|
||||
except Exception as e:
|
||||
self.logger.error(f"Failed to add video routes: {e}")
|
||||
|
||||
@self.app.get("/debug/camera-manager")
|
||||
async def debug_camera_manager():
|
||||
"""Debug endpoint to check camera manager state"""
|
||||
try:
|
||||
if not self.camera_manager:
|
||||
return {"error": "Camera manager not available"}
|
||||
|
||||
return {
|
||||
"available_cameras": len(self.camera_manager.available_cameras),
|
||||
"camera_recorders": list(self.camera_manager.camera_recorders.keys()),
|
||||
"camera_streamers": list(self.camera_manager.camera_streamers.keys()),
|
||||
"streamer_states": {
|
||||
name: {
|
||||
"exists": streamer is not None,
|
||||
"is_streaming": streamer.is_streaming() if streamer else False,
|
||||
"streaming": getattr(streamer, 'streaming', False) if streamer else False
|
||||
}
|
||||
for name, streamer in self.camera_manager.camera_streamers.items()
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
def _setup_event_subscriptions(self):
|
||||
"""Setup event subscriptions for WebSocket broadcasting"""
|
||||
|
||||
|
||||
@@ -460,12 +460,16 @@ class CameraManager:
|
||||
|
||||
def _initialize_streamers(self) -> None:
|
||||
"""Initialize camera streamers for configured cameras"""
|
||||
self.logger.info("Starting camera streamer initialization...")
|
||||
with self._lock:
|
||||
for camera_config in self.config.cameras:
|
||||
if not camera_config.enabled:
|
||||
self.logger.debug(f"Skipping disabled camera: {camera_config.name}")
|
||||
continue
|
||||
|
||||
try:
|
||||
self.logger.info(f"Initializing streamer for camera: {camera_config.name}")
|
||||
|
||||
# Find matching physical camera
|
||||
device_info = self._find_camera_device(camera_config.name)
|
||||
if device_info is None:
|
||||
@@ -481,6 +485,10 @@ class CameraManager:
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error initializing streamer for {camera_config.name}: {e}")
|
||||
import traceback
|
||||
self.logger.error(f"Traceback: {traceback.format_exc()}")
|
||||
|
||||
self.logger.info(f"Camera streamer initialization complete. Created {len(self.camera_streamers)} streamers: {list(self.camera_streamers.keys())}")
|
||||
|
||||
def get_camera_streamer(self, camera_name: str) -> Optional[CameraStreamer]:
|
||||
"""Get camera streamer for a specific camera"""
|
||||
|
||||
@@ -172,14 +172,37 @@ class CameraMonitor:
|
||||
if not device_info:
|
||||
return "disconnected", "Camera device not found", None
|
||||
|
||||
# ALWAYS check our streamer state first, before doing any camera availability tests
|
||||
streamer = self.camera_manager.camera_streamers.get(camera_name)
|
||||
self.logger.info(f"Checking streamer for {camera_name}: {streamer}")
|
||||
if streamer and streamer.is_streaming():
|
||||
self.logger.info(f"Camera {camera_name} is streaming - setting status to streaming")
|
||||
return "streaming", "Camera streaming (live preview)", self._get_device_info_dict(device_info)
|
||||
|
||||
# Also check if our recorder is active
|
||||
recorder = self.camera_manager.camera_recorders.get(camera_name)
|
||||
if recorder and recorder.hCamera and recorder.recording:
|
||||
self.logger.info(f"Camera {camera_name} is recording - setting status to available")
|
||||
return "available", "Camera recording (in use by system)", self._get_device_info_dict(device_info)
|
||||
|
||||
# Check if camera is already opened by another process
|
||||
if mvsdk.CameraIsOpened(device_info):
|
||||
# Camera is opened - check if it's our recorder that's currently recording
|
||||
recorder = self.camera_manager.camera_recorders.get(camera_name)
|
||||
if recorder and recorder.hCamera and recorder.recording:
|
||||
return "available", "Camera recording (in use by system)", self._get_device_info_dict(device_info)
|
||||
else:
|
||||
try:
|
||||
self.logger.info(f"Checking if camera {camera_name} is opened...")
|
||||
is_opened = mvsdk.CameraIsOpened(device_info)
|
||||
self.logger.info(f"CameraIsOpened result for {camera_name}: {is_opened}")
|
||||
|
||||
if is_opened:
|
||||
self.logger.info(f"Camera {camera_name} is opened by another process - setting status to busy")
|
||||
return "busy", "Camera opened by another process", self._get_device_info_dict(device_info)
|
||||
else:
|
||||
self.logger.info(f"Camera {camera_name} is not opened, will try initialization")
|
||||
# Camera is not opened, so we can try to initialize it
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
self.logger.warning(f"CameraIsOpened failed for {camera_name}: {e}")
|
||||
# If we can't determine the status, try to initialize to see what happens
|
||||
self.logger.info(f"CameraIsOpened failed for {camera_name}, will try initialization: {e}")
|
||||
|
||||
# Try to initialize camera briefly to test availability
|
||||
try:
|
||||
|
||||
@@ -28,6 +28,7 @@ class CameraStatus(Enum):
|
||||
UNKNOWN = "unknown"
|
||||
AVAILABLE = "available"
|
||||
BUSY = "busy"
|
||||
STREAMING = "streaming" # New status for when camera is streaming
|
||||
ERROR = "error"
|
||||
DISCONNECTED = "disconnected"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user