some bullshit

This commit is contained in:
rattatwinko
2025-05-27 16:05:04 +02:00
parent 64b472ad8e
commit 82f435b8c3
5 changed files with 5517 additions and 272 deletions

View File

@@ -284,11 +284,13 @@ class CameraStream:
self.frame_timeout = 5.0 # Timeout after 5 seconds without frames
self.reconnect_interval = 5.0 # Try to reconnect every 5 seconds
self.last_reconnect_attempt = 0
self.connection_retries = 0
self.max_retries = 3
def start(self):
"""Start the camera stream"""
"""Start the camera stream with improved error handling"""
if self.running:
return
return False
try:
if self.is_network_camera:
@@ -315,6 +317,16 @@ class CameraStream:
logger.info(f"Connecting to network camera: {url}")
self.cap = cv2.VideoCapture(url)
# Wait for connection
retry_count = 0
while not self.cap.isOpened() and retry_count < 3:
time.sleep(1)
retry_count += 1
self.cap.open(url)
if not self.cap.isOpened():
raise Exception(f"Failed to connect to network camera at {url}")
else:
# Handle local camera
self.cap = cv2.VideoCapture(self.camera_id)
@@ -329,6 +341,7 @@ class CameraStream:
self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
self.running = True
self.connection_retries = 0
self.thread = threading.Thread(target=self._capture_loop)
self.thread.daemon = True
self.thread.start()
@@ -338,6 +351,7 @@ class CameraStream:
if self.cap:
self.cap.release()
self.cap = None
self.connection_retries += 1
return False
def stop(self):
@@ -356,15 +370,23 @@ class CameraStream:
break
def _capture_loop(self):
"""Main capture loop with automatic reconnection"""
"""Main capture loop with improved error handling and reconnection"""
while self.running:
try:
if not self.cap or not self.cap.isOpened():
current_time = time.time()
if current_time - self.last_reconnect_attempt >= self.reconnect_interval:
logger.info(f"Attempting to reconnect camera {self.camera_id}")
self.last_reconnect_attempt = current_time
self.start()
if self.connection_retries < self.max_retries:
logger.info(f"Attempting to reconnect camera {self.camera_id}")
self.last_reconnect_attempt = current_time
if self.start():
logger.info(f"Successfully reconnected camera {self.camera_id}")
else:
logger.warning(f"Failed to reconnect camera {self.camera_id}")
else:
logger.error(f"Max reconnection attempts reached for camera {self.camera_id}")
self.running = False
break
time.sleep(1)
continue
@@ -511,10 +533,16 @@ def video_feed(camera_id):
return Response(gen_frames(camera_id),
mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/scan_cameras')
def scan_cameras_route():
"""Scan and return available cameras"""
cameras = scan_cameras_silently()
return jsonify({'cameras': cameras})
@app.route('/cameras')
def get_cameras():
"""Get list of available cameras"""
# Scan for local cameras silently
# Get local cameras
cameras = scan_cameras_silently()
# Add network cameras
@@ -523,7 +551,9 @@ def get_cameras():
cameras.append({
'id': f'net:{name}',
'type': 'network',
'name': f'{name} ({url})'
'name': f'{name} ({url})',
'width': 1280, # Default width for network cameras
'height': 720 # Default height for network cameras
})
# Add status information for active cameras
@@ -536,7 +566,7 @@ def get_cameras():
camera['active'] = False
camera['status'] = 'disconnected'
return jsonify(cameras)
return jsonify({'cameras': cameras})
@app.route('/add_camera/<path:camera_id>')
def add_camera(camera_id):
@@ -597,6 +627,109 @@ def load_model():
success = camera_manager.detector.load_yolo_model(model_dir)
return jsonify({'success': success})
@app.route('/check_model')
def check_model():
"""Check YOLO model status"""
return jsonify({
'model_loaded': camera_manager.detector.model_loaded,
'model_name': camera_manager.detector.current_model,
'cuda_available': camera_manager.detector.cuda_available
})
@app.route('/model_info')
def model_info():
"""Get detailed model information"""
detector = camera_manager.detector
return jsonify({
'model_loaded': detector.model_loaded,
'model_name': detector.current_model,
'cuda_available': detector.cuda_available,
'classes': detector.classes,
'confidence_threshold': detector.confidence_threshold
})
@app.route('/update_model_settings', methods=['POST'])
def update_model_settings():
"""Update model settings"""
data = request.json
if 'confidence_threshold' in data:
try:
threshold = float(data['confidence_threshold'])
if 0 <= threshold <= 1:
camera_manager.detector.confidence_threshold = threshold
return jsonify({'success': True})
except ValueError:
pass
return jsonify({'success': False, 'error': 'Invalid settings'})
@app.route('/network_cameras/list')
def list_network_cameras():
"""List all configured network cameras"""
cameras = []
for name, info in camera_manager.network_cameras.items():
if isinstance(info, dict):
cameras.append({
'name': name,
'url': info['url'],
'username': info.get('username'),
'has_auth': bool(info.get('username') and info.get('password'))
})
else:
cameras.append({
'name': name,
'url': info,
'has_auth': False
})
return jsonify({'cameras': cameras})
@app.route('/network_cameras/remove/<name>', methods=['POST'])
def remove_network_camera(name):
"""Remove a network camera"""
success = camera_manager.remove_network_camera(name)
return jsonify({'success': success})
@app.route('/camera_settings/<path:camera_id>', methods=['GET', 'POST'])
def camera_settings(camera_id):
"""Get or update camera settings"""
camera = camera_manager.get_camera(camera_id)
if not camera:
return jsonify({'success': False, 'error': 'Camera not found'})
if request.method == 'POST':
data = request.json
try:
if 'width' in data and 'height' in data:
width = int(data['width'])
height = int(data['height'])
if camera.cap:
camera.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
camera.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
if 'fps' in data:
fps = int(data['fps'])
if camera.cap:
camera.cap.set(cv2.CAP_PROP_FPS, fps)
if 'reconnect' in data and data['reconnect']:
# Force camera reconnection
camera.stop()
time.sleep(1) # Wait for cleanup
camera.start()
return jsonify({'success': True})
except Exception as e:
logger.error(f"Error updating camera settings: {e}")
return jsonify({'success': False, 'error': str(e)})
else:
if not camera.cap:
return jsonify({'success': False, 'error': 'Camera not connected'})
settings = {
'width': int(camera.cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
'height': int(camera.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),
'fps': int(camera.cap.get(cv2.CAP_PROP_FPS)),
'is_network': camera.is_network_camera,
'status': 'connected' if camera.cap and camera.cap.isOpened() else 'disconnected'
}
return jsonify({'success': True, 'settings': settings})
# Reduce camera scanning noise
def scan_cameras_silently():
"""Scan for cameras while suppressing OpenCV warnings"""