| from dotenv import load_dotenv |
| load_dotenv() |
|
|
| from fastapi import FastAPI |
| from fastapi.middleware.cors import CORSMiddleware |
| from backend.db.database import engine, Base |
| from backend.api.routers import alerts, analytics, video, stream, archive, stream_vlm, intelligence, settings, smart_bin, chatbot |
| from backend.services.retention_scheduler import RetentionScheduler |
| from backend.services.ml_service import ml_service |
| import os |
| import shutil |
|
|
| |
| Base.metadata.create_all(bind=engine) |
|
|
| |
| app = FastAPI(title="AURORA-SENTINEL API", version="2.0.0") |
|
|
| from fastapi.staticfiles import StaticFiles |
|
|
| |
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| |
| os.makedirs("storage/recordings", exist_ok=True) |
| app.mount("/recordings", StaticFiles(directory="storage/recordings"), name="recordings") |
|
|
| from fastapi.responses import JSONResponse |
| from fastapi import Request |
|
|
| @app.exception_handler(Exception) |
| async def global_exception_handler(request: Request, exc: Exception): |
| print(f"GLOBAL EXCEPTION: {exc}") |
| import traceback |
| traceback.print_exc() |
| return JSONResponse( |
| status_code=500, |
| content={"detail": "Internal Server Error", "error": str(exc)}, |
| headers={"Access-Control-Allow-Origin": "*"} |
| ) |
|
|
| |
| _retention_scheduler = RetentionScheduler() |
|
|
| @app.on_event("startup") |
| async def startup_event(): |
| print("STARTUP: Starting ml_service.load_models()...") |
| try: |
| ml_service.load_models() |
| print("STARTUP: ml_service.load_models() completed.") |
| except Exception as e: |
| print(f"STARTUP ERROR: {e}") |
| import traceback |
| traceback.print_exc() |
| raise e |
| await _retention_scheduler.start() |
| print("STARTUP: RetentionScheduler started.") |
|
|
| |
|
|
| |
|
|
| |
| print("Including alerts router...") |
| app.include_router(alerts.router, prefix="/alerts", tags=["Alerts"]) |
| print("Including analytics router...") |
| app.include_router(analytics.router, prefix="/analytics", tags=["Analytics"]) |
| print("Including stream router...") |
| app.include_router(stream.router, prefix="/ws", tags=["Live Stream"]) |
| print("Including stream_vlm router...") |
| app.include_router(stream_vlm.router, prefix="/vlm", tags=["Intelligent Stream"]) |
| print("Including video router...") |
| app.include_router(video.router, tags=["Video Processing"]) |
| print("Including archive router...") |
| app.include_router(archive.router, prefix="/archive", tags=["Archive"]) |
| print("Including intelligence router...") |
| app.include_router(intelligence.router, prefix="/intelligence", tags=["Intelligence"]) |
| print("Including settings router...") |
| app.include_router(settings.router, prefix="/settings", tags=["Settings"]) |
| print("Including smart_bin router...") |
| app.include_router(smart_bin.router, prefix="/smart-bin", tags=["Smart Bin"]) |
| print("Including chatbot router...") |
| app.include_router(chatbot.router, prefix="/chatbot", tags=["Chatbot"]) |
| print("All routers included.") |
|
|
| |
| from fastapi.staticfiles import StaticFiles |
| from fastapi.responses import FileResponse |
|
|
| |
| if os.path.exists("frontend/build"): |
| app.mount("/", StaticFiles(directory="frontend/build", html=True), name="frontend") |
| |
| @app.get("/{full_path:path}") |
| async def serve_frontend(full_path: str): |
| |
| if full_path.split('/')[0] in ["alerts", "analytics", "ws", "vlm", "process", "archive", "intelligence", "health", "docs", "openapi.json"]: |
| return JSONResponse(status_code=404, content={"detail": "Not Found"}) |
| return FileResponse("frontend/build/index.html") |
| else: |
| print("WARNING: frontend/build directory not found. Frontend will not be served by backend.") |
|
|
|
|
| @app.get("/") |
| async def root(): |
| return { |
| "message": "AURORA-SENTINEL API", |
| "version": "2.0.0", |
| "status": "operational", |
| "models_loaded": ml_service.loaded |
| } |
|
|
| @app.get("/health") |
| async def health_check(): |
| """System health check""" |
| |
| try: |
| import chromadb |
| chroma_ok = True |
| except Exception: |
| chroma_ok = False |
|
|
| try: |
| import sentence_transformers |
| st_ok = True |
| except Exception: |
| st_ok = False |
|
|
| try: |
| import google.generativeai |
| gemini_pkg_ok = True |
| except Exception: |
| gemini_pkg_ok = False |
|
|
| try: |
| import ollama |
| ollama_pkg_ok = True |
| except Exception: |
| ollama_pkg_ok = False |
|
|
| ffmpeg_ok = bool(shutil.which("ffmpeg")) |
| |
| |
| ai_model_status = {} |
| try: |
| |
| import sys |
| ai_layer_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'ai-intelligence-layer') |
| if ai_layer_path not in sys.path: |
| sys.path.insert(0, ai_layer_path) |
| |
| from aiRouter_enhanced import get_model_status |
| ai_model_status = get_model_status() |
| except Exception as e: |
| print(f"Could not get AI model status: {e}") |
| ai_model_status = { |
| 'error': 'AI model status unavailable', |
| 'details': str(e) |
| } |
|
|
| return { |
| "status": "healthy", |
| "models_loaded": ml_service.loaded, |
| "gpu_available": getattr(ml_service.detector, 'device', 'cpu') == 'cuda' if ml_service.detector else False, |
| "database": "connected", |
| "ai_models": ai_model_status, |
| "optional_features": { |
| "gemini_pkg": gemini_pkg_ok, |
| "ollama_pkg": ollama_pkg_ok, |
| "chromadb": chroma_ok, |
| "sentence_transformers": st_ok, |
| "ffmpeg": ffmpeg_ok |
| } |
| } |
|
|
| if __name__ == "__main__": |
| import uvicorn |
| uvicorn.run("backend.api.main:app", host="0.0.0.0", port=8000, reload=True) |
|
|