import asyncio from fastapi import FastAPI, Form, HTTPException, Request from fastapi.responses import HTMLResponse, JSONResponse import uvicorn HTML_TEMPLATE = """ SmartWave Technician Portal

SmartWave Orchestrator System Logs

Loading logs...

Telemetry Control

""" def create_app(get_logs_cb, telemetry_cb, is_tech_mode_cb) -> FastAPI: """Factory creating FastAPI app with injected handler callbacks.""" app = FastAPI(title="Technician Portal") # Attach callbacks to app.state app.state.get_systemd_logs = get_logs_cb app.state.handle_telemetry_request = telemetry_cb app.state.is_tech_mode = is_tech_mode_cb # Middleware to block traffic when TECHNICIAN_MODE is False @app.middleware("http") async def enforce_technician_mode(request: Request, call_next): if not request.app.state.is_tech_mode(): return JSONResponse( status_code=503, content={"detail": "Technician mode is disabled."} ) return await call_next(request) @app.get("/", response_class=HTMLResponse) async def serve_dashboard(): return HTML_TEMPLATE @app.get("/api/logs") async def api_get_logs(request: Request): try: logs = await request.app.state.get_systemd_logs(lines=200, service_name="smartwave") return JSONResponse(content=logs) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.post("/api/telemetry") async def api_trigger_telemetry(request: Request, endpoint: str = Form(...)): try: await request.app.state.handle_telemetry_request(endpoint=endpoint, do_timeout=True) return {"status": "ok", "message": f"Telemetry request sent to {endpoint}"} except Exception as e: raise HTTPException(status_code=500, detail=f"Telemetry trigger failed: {str(e)}") return app async def start_technician_web_server(get_logs_cb, telemetry_cb, is_tech_mode_cb, host="192.168.50.1", port=8080): """Asynchronous server launcher meant to run within main.py's event loop.""" app = create_app(get_logs_cb, telemetry_cb, is_tech_mode_cb) config = uvicorn.Config(app, host=host, port=port, log_level="info") server = uvicorn.Server(config) await server.serve()