124 lines
4.4 KiB
Python
124 lines
4.4 KiB
Python
"""
|
|
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 app.seismo.database import get_db
|
|
from app.seismo.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 != "sound_level_meter":
|
|
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 != "sound_level_meter":
|
|
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": "sound_level_meter",
|
|
"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 != "sound_level_meter":
|
|
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"
|
|
})
|