127 lines
4.1 KiB
Python
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()
|