Files
vna_system/vna_system/main.py
2025-11-24 22:21:30 +03:00

127 lines
4.1 KiB
Python

import logging
import os
from contextlib import asynccontextmanager
from pathlib import Path
import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
import vna_system.core.singletons as singletons
from vna_system.api.endpoints import acquisition, health, settings, web_ui, laser
from vna_system.api.websockets import processing as ws_processing
from vna_system.core.config import API_HOST, API_PORT
from vna_system.core.logging.logger import get_component_logger, setup_logging
PROJECT_ROOT = Path(__file__).resolve().parents[1]
LOG_DIR = PROJECT_ROOT / "logs"
setup_logging(log_level=os.getenv("VNA_LOG_LEVEL", "INFO"), log_dir=LOG_DIR)
for noisy in (
"uvicorn.error",
"uvicorn.access",
):
logging.getLogger(noisy).setLevel(logging.ERROR)
logger = get_component_logger(__file__)
@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info("Starting VNA API Server")
try:
logger.info("Starting data acquisition")
singletons.vna_data_acquisition_instance.start()
logger.info("Starting processor system")
singletons.processor_manager.start_processing()
logger.info(
"Processor system started",
processors=singletons.processor_manager.list_processors(),
)
# Try to connect to laser controller (optional, non-blocking)
logger.info("Attempting to connect to laser control hardware")
try:
result = singletons.laser_controller_instance.connect()
if result["success"]:
logger.info("Laser controller connected", port=result.get("port"))
else:
logger.warning("Laser controller connection failed (will retry on demand)", message=result.get("message"))
except Exception as e:
logger.warning("Failed to connect to laser controller on startup (will retry on demand)", error=str(e))
logger.info("VNA API Server started successfully")
yield
except Exception as exc:
logger.error("Error during startup", error=repr(exc))
raise
logger.info("Shutting down VNA API Server")
# Disconnect laser controller
if singletons.laser_controller_instance and singletons.laser_controller_instance.is_connected:
try:
singletons.laser_controller_instance.disconnect()
logger.info("Laser controller disconnected")
except Exception as e:
logger.warning("Error disconnecting laser controller", error=str(e))
if singletons.processor_manager:
singletons.processor_manager.stop_processing()
logger.info("Processor system stopped")
if getattr(singletons, "vna_data_acquisition_instance", None) and singletons.vna_data_acquisition_instance._running:
singletons.vna_data_acquisition_instance.stop()
logger.info("Acquisition stopped")
logger.info("VNA API Server shutdown complete")
app = FastAPI(
title="VNA System API",
description="Real-time VNA data acquisition and processing API",
version="1.0.0",
lifespan=lifespan,
)
WEB_UI_DIR = Path(__file__).parent / "web_ui"
STATIC_DIR = WEB_UI_DIR / "static"
if STATIC_DIR.exists():
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
logger.info("Mounted static files", directory=str(STATIC_DIR))
else:
logger.warning("Static directory not found", directory=str(STATIC_DIR))
app.include_router(web_ui.router)
app.include_router(health.router)
app.include_router(acquisition.router)
app.include_router(settings.router)
app.include_router(laser.router)
app.include_router(ws_processing.router)
def main() -> None:
host = os.getenv("VNA_HOST", API_HOST)
port_env = os.getenv("VNA_PORT")
if port_env is not None:
try:
port = int(port_env)
except ValueError:
logger.warning("Invalid VNA_PORT, falling back to config", VNA_PORT=port_env)
port = API_PORT
else:
port = API_PORT
logger.info("Launching Uvicorn", host=host, port=port)
uvicorn.run(
"vna_system.main:app",
host=host,
port=port,
log_level="info",
reload=False,
)
if __name__ == "__main__":
main()