""" Sound Level Meter UI Router Provides endpoints for SLM dashboard cards, detail pages, and real-time data. """ from fastapi import APIRouter, Depends, HTTPException, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates from sqlalchemy.orm import Session from datetime import datetime import httpx import logging import os from backend.database import get_db from backend.models import RosterUnit logger = logging.getLogger(__name__) router = APIRouter(prefix="/slm", tags=["slm-ui"]) templates = Jinja2Templates(directory="templates") SLMM_BASE_URL = os.getenv("SLMM_BASE_URL", "http://172.19.0.1:8100") @router.get("/{unit_id}", response_class=HTMLResponse) async def slm_detail_page(request: Request, unit_id: str, db: Session = Depends(get_db)): """Sound level meter detail page with controls.""" # Get roster unit unit = db.query(RosterUnit).filter_by(id=unit_id).first() if not unit or unit.device_type != "slm": raise HTTPException(status_code=404, detail="Sound level meter not found") return templates.TemplateResponse("slm_detail.html", { "request": request, "unit": unit, "unit_id": unit_id }) @router.get("/api/{unit_id}/summary") async def get_slm_summary(unit_id: str, db: Session = Depends(get_db)): """Get SLM summary data for dashboard card.""" # Get roster unit unit = db.query(RosterUnit).filter_by(id=unit_id).first() if not unit or unit.device_type != "slm": raise HTTPException(status_code=404, detail="Sound level meter not found") # Try to get live status from SLMM status_data = None try: async with httpx.AsyncClient(timeout=3.0) as client: response = await client.get(f"{SLMM_BASE_URL}/api/nl43/{unit_id}/status") if response.status_code == 200: status_data = response.json().get("data") except Exception as e: logger.warning(f"Failed to get SLM status for {unit_id}: {e}") return { "unit_id": unit_id, "device_type": "slm", "deployed": unit.deployed, "model": unit.slm_model or "NL-43", "location": unit.address or unit.location, "coordinates": unit.coordinates, "note": unit.note, "status": status_data, "last_check": unit.slm_last_check.isoformat() if unit.slm_last_check else None, } @router.get("/partials/{unit_id}/card", response_class=HTMLResponse) async def slm_dashboard_card(request: Request, unit_id: str, db: Session = Depends(get_db)): """Render SLM dashboard card partial.""" summary = await get_slm_summary(unit_id, db) return templates.TemplateResponse("partials/slm_card.html", { "request": request, "slm": summary }) @router.get("/partials/{unit_id}/controls", response_class=HTMLResponse) async def slm_controls_partial(request: Request, unit_id: str, db: Session = Depends(get_db)): """Render SLM control panel partial.""" unit = db.query(RosterUnit).filter_by(id=unit_id).first() if not unit or unit.device_type != "slm": raise HTTPException(status_code=404, detail="Sound level meter not found") # Get current status from SLMM measurement_state = None battery_level = None try: async with httpx.AsyncClient(timeout=3.0) as client: # Get measurement state state_response = await client.get( f"{SLMM_BASE_URL}/api/nl43/{unit_id}/measurement-state" ) if state_response.status_code == 200: measurement_state = state_response.json().get("measurement_state") # Get battery level battery_response = await client.get( f"{SLMM_BASE_URL}/api/nl43/{unit_id}/battery" ) if battery_response.status_code == 200: battery_level = battery_response.json().get("battery_level") except Exception as e: logger.warning(f"Failed to get SLM control data for {unit_id}: {e}") return templates.TemplateResponse("partials/slm_controls.html", { "request": request, "unit_id": unit_id, "unit": unit, "measurement_state": measurement_state, "battery_level": battery_level, "is_measuring": measurement_state == "Start" })