Fix: got data from backend

This commit is contained in:
ziesorx 2025-09-13 01:00:49 +07:00
parent 42a8325faf
commit 086ba0e4d3
4 changed files with 107 additions and 12 deletions

9
app.py
View file

@ -5,6 +5,7 @@ This replaces the monolithic app.py with a clean, maintainable structure
using dependency injection and singleton managers. using dependency injection and singleton managers.
""" """
import logging import logging
import os
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from fastapi import FastAPI, WebSocket, HTTPException from fastapi import FastAPI, WebSocket, HTTPException
from fastapi.responses import Response from fastapi.responses import Response
@ -91,6 +92,14 @@ async def lifespan(app: FastAPI):
camera_manager.clear_all() camera_manager.clear_all()
pipeline_manager.clear_all() pipeline_manager.clear_all()
# Clear model cache files on disk
import shutil
from detector_worker.core.config import MODELS_DIR
if os.path.exists(MODELS_DIR):
logger.info(f"Clearing model cache directory: {MODELS_DIR}")
shutil.rmtree(MODELS_DIR)
logger.info("Model cache directory cleared")
# Clear dependency container singletons # Clear dependency container singletons
container.get_container().clear_singletons() container.get_container().clear_singletons()

View file

@ -7,6 +7,7 @@ and coordination between stream processing and detection pipelines.
import asyncio import asyncio
import json import json
import logging import logging
import os
import time import time
import traceback import traceback
import uuid import uuid
@ -429,11 +430,38 @@ class WebSocketHandler:
print(f"📦 Subscription {i+1}: {sub_id} | Model {model_id}") print(f"📦 Subscription {i+1}: {sub_id} | Model {model_id}")
# Track unique models for download # Track unique models for download - check if model already exists locally
if model_id and model_url: if model_id and model_url:
if model_id not in unique_models: if model_id not in unique_models:
# Check if model directory already exists on disk
from ..core.config import MODELS_DIR
model_dir = os.path.join(MODELS_DIR, str(model_id))
print(f"🔍 Checking model directory: {model_dir}")
logger.info(f"Checking if model {model_id} exists at: {model_dir}")
if os.path.exists(model_dir) and os.path.isdir(model_dir):
# Check if directory has content (not empty)
dir_contents = os.listdir(model_dir)
actual_contents = [f for f in dir_contents if not f.startswith('.')]
print(f"📋 Directory contents: {dir_contents}")
print(f"📋 Filtered contents: {actual_contents}")
logger.info(f"Model {model_id} directory contents: {actual_contents}")
if actual_contents:
print(f"📁 Model {model_id} already exists locally, skipping download")
logger.info(f"Skipping download for model {model_id} - already exists")
else:
print(f"📁 Model {model_id} directory exists but empty, will download")
unique_models[model_id] = model_url unique_models[model_id] = model_url
print(f"🎯 New model found: ID {model_id}") print(f"🎯 New model found: ID {model_id}")
logger.info(f"Model {model_id} directory empty, adding to download queue")
else:
print(f"📁 Model {model_id} directory does not exist, will download")
unique_models[model_id] = model_url
print(f"🎯 New model found: ID {model_id}")
logger.info(f"Model {model_id} directory not found, adding to download queue")
else: else:
print(f"🔄 Model {model_id} already tracked") print(f"🔄 Model {model_id} already tracked")

View file

@ -251,6 +251,27 @@ class ModelManager:
if parsed.scheme in ['http', 'https']: if parsed.scheme in ['http', 'https']:
# Create model_id subfolder structure # Create model_id subfolder structure
model_dir = os.path.join(self.models_dir, str(model_id)) model_dir = os.path.join(self.models_dir, str(model_id))
# Simple check: if model_id directory already exists, skip download entirely
if os.path.exists(model_dir) and os.path.isdir(model_dir):
dir_contents = os.listdir(model_dir)
# Filter out hidden files like .DS_Store
actual_contents = [f for f in dir_contents if not f.startswith('.')]
if actual_contents:
logger.info(f"Model {model_id} directory already exists, skipping download")
# Look for existing MPTA file
mpta_files = [f for f in actual_contents if f.endswith('.mpta')]
if mpta_files:
existing_mpta = os.path.join(model_dir, mpta_files[0])
logger.info(f"Using existing MPTA file: {existing_mpta}")
return existing_mpta
# No MPTA file but directory exists - this shouldn't happen in normal flow
# But let's handle it by proceeding with download
logger.warning(f"Model {model_id} directory exists but no MPTA file found")
# Create the directory if it doesn't exist
os.makedirs(model_dir, exist_ok=True) os.makedirs(model_dir, exist_ok=True)
# Generate cache filename # Generate cache filename
@ -260,7 +281,7 @@ class ModelManager:
cache_path = os.path.join(model_dir, filename) cache_path = os.path.join(model_dir, filename)
# Check if already cached # Check if exact MPTA file already cached
if os.path.exists(cache_path): if os.path.exists(cache_path):
logger.info(f"Using cached model file: {cache_path}") logger.info(f"Using cached model file: {cache_path}")
return cache_path return cache_path

View file

@ -134,8 +134,13 @@ class StreamManager:
camera_id: str, camera_id: str,
rtsp_url: Optional[str] = None, rtsp_url: Optional[str] = None,
snapshot_url: Optional[str] = None, snapshot_url: Optional[str] = None,
snapshot_interval: Optional[int] = None) -> StreamInfo: snapshot_interval: Optional[int] = None,
"""Create StreamInfo object based on stream type.""" subscription_metadata: Optional[Dict[str, Any]] = None) -> StreamInfo:
"""Create StreamInfo object based on stream type with subscription metadata."""
# Extract subscription metadata if provided
metadata = subscription_metadata or {}
if snapshot_url and snapshot_interval: if snapshot_url and snapshot_interval:
return StreamInfo( return StreamInfo(
camera_id=camera_id, camera_id=camera_id,
@ -143,7 +148,15 @@ class StreamManager:
stream_type="snapshot", stream_type="snapshot",
snapshot_interval=snapshot_interval, snapshot_interval=snapshot_interval,
buffer=queue.Queue(maxsize=SHARED_STREAM_BUFFER_SIZE), buffer=queue.Queue(maxsize=SHARED_STREAM_BUFFER_SIZE),
stop_event=threading.Event() stop_event=threading.Event(),
# Add subscription metadata
subscriptionIdentifier=metadata.get("subscriptionIdentifier"),
modelId=metadata.get("modelId"),
modelName=metadata.get("modelName"),
cropX1=metadata.get("cropX1"),
cropY1=metadata.get("cropY1"),
cropX2=metadata.get("cropX2"),
cropY2=metadata.get("cropY2")
) )
elif rtsp_url: elif rtsp_url:
return StreamInfo( return StreamInfo(
@ -151,7 +164,15 @@ class StreamManager:
stream_url=rtsp_url, stream_url=rtsp_url,
stream_type="rtsp", stream_type="rtsp",
buffer=queue.Queue(maxsize=SHARED_STREAM_BUFFER_SIZE), buffer=queue.Queue(maxsize=SHARED_STREAM_BUFFER_SIZE),
stop_event=threading.Event() stop_event=threading.Event(),
# Add subscription metadata
subscriptionIdentifier=metadata.get("subscriptionIdentifier"),
modelId=metadata.get("modelId"),
modelName=metadata.get("modelName"),
cropX1=metadata.get("cropX1"),
cropY1=metadata.get("cropY1"),
cropX2=metadata.get("cropX2"),
cropY2=metadata.get("cropY2")
) )
else: else:
raise ValueError("Must provide either RTSP URL or snapshot URL with interval") raise ValueError("Must provide either RTSP URL or snapshot URL with interval")
@ -162,7 +183,8 @@ class StreamManager:
subscriber_id: str, subscriber_id: str,
rtsp_url: Optional[str] = None, rtsp_url: Optional[str] = None,
snapshot_url: Optional[str] = None, snapshot_url: Optional[str] = None,
snapshot_interval: Optional[int] = None) -> bool: snapshot_interval: Optional[int] = None,
subscription_metadata: Optional[Dict[str, Any]] = None) -> bool:
""" """
Create a stream subscription. Create a stream subscription.
@ -194,7 +216,7 @@ class StreamManager:
# Create or get existing stream # Create or get existing stream
if camera_id not in self._streams: if camera_id not in self._streams:
stream_info = self._create_stream_info( stream_info = self._create_stream_info(
camera_id, rtsp_url, snapshot_url, snapshot_interval camera_id, rtsp_url, snapshot_url, snapshot_interval, subscription_metadata
) )
self._streams[camera_id] = stream_info self._streams[camera_id] = stream_info
@ -642,6 +664,19 @@ class StreamManager:
# Create a subscriber_id (for WebSocket compatibility, use the subscription_id) # Create a subscriber_id (for WebSocket compatibility, use the subscription_id)
subscriber_id = f"websocket_{int(time.time() * 1000)}" subscriber_id = f"websocket_{int(time.time() * 1000)}"
# Extract subscription metadata from payload
subscription_metadata = {
"subscriptionIdentifier": payload.get("subscriptionIdentifier"),
"modelId": payload.get("modelId"),
"modelName": payload.get("modelName"),
"cropX1": payload.get("cropX1"),
"cropY1": payload.get("cropY1"),
"cropX2": payload.get("cropX2"),
"cropY2": payload.get("cropY2")
}
logger.info(f"Extracted subscription metadata for camera {camera_id}: {subscription_metadata}")
# Create subscription based on available URL type # Create subscription based on available URL type
if rtsp_url and rtsp_url.strip(): if rtsp_url and rtsp_url.strip():
logger.info(f"Creating RTSP stream for camera {camera_id}: {rtsp_url}") logger.info(f"Creating RTSP stream for camera {camera_id}: {rtsp_url}")
@ -649,7 +684,8 @@ class StreamManager:
subscription_id=subscription_id, subscription_id=subscription_id,
camera_id=camera_id, camera_id=camera_id,
subscriber_id=subscriber_id, subscriber_id=subscriber_id,
rtsp_url=rtsp_url.strip() rtsp_url=rtsp_url.strip(),
subscription_metadata=subscription_metadata
) )
elif snapshot_url and snapshot_url.strip(): elif snapshot_url and snapshot_url.strip():
logger.info(f"Creating snapshot stream for camera {camera_id}: {snapshot_url}") logger.info(f"Creating snapshot stream for camera {camera_id}: {snapshot_url}")
@ -658,7 +694,8 @@ class StreamManager:
camera_id=camera_id, camera_id=camera_id,
subscriber_id=subscriber_id, subscriber_id=subscriber_id,
snapshot_url=snapshot_url.strip(), snapshot_url=snapshot_url.strip(),
snapshot_interval=snapshot_interval snapshot_interval=snapshot_interval,
subscription_metadata=subscription_metadata
) )
else: else:
logger.error(f"No valid stream URL provided for camera {camera_id}. " logger.error(f"No valid stream URL provided for camera {camera_id}. "