Initial commit: GSPro Remote MVP - Phase 1 complete
This commit is contained in:
commit
74ca4b38eb
50 changed files with 12818 additions and 0 deletions
115
backend/app/main.py
Normal file
115
backend/app/main.py
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
"""
|
||||
Main FastAPI application for GSPro Remote backend.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from .api import actions, config, system, vision
|
||||
from .core.config import AppConfig, get_config
|
||||
from .core.mdns import MDNSService
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""
|
||||
Application lifespan manager for startup/shutdown tasks.
|
||||
"""
|
||||
# Startup
|
||||
logger.info("Starting GSPro Remote backend v0.1.0")
|
||||
|
||||
# Load configuration
|
||||
config = get_config()
|
||||
logger.info(f"Configuration loaded from {config.config_path}")
|
||||
|
||||
# Start mDNS service if enabled
|
||||
mdns_service = None
|
||||
if config.server.mdns_enabled:
|
||||
try:
|
||||
mdns_service = MDNSService(name="gsproapp", port=config.server.port, service_type="_http._tcp.local.")
|
||||
mdns_service.start()
|
||||
logger.info(f"mDNS service started: gsproapp.local:{config.server.port}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to start mDNS service: {e}")
|
||||
|
||||
yield
|
||||
|
||||
# Shutdown
|
||||
logger.info("Shutting down GSPro Remote backend")
|
||||
|
||||
# Stop mDNS service
|
||||
if mdns_service:
|
||||
mdns_service.stop()
|
||||
logger.info("mDNS service stopped")
|
||||
|
||||
# Save configuration
|
||||
config.save()
|
||||
logger.info("Configuration saved")
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""
|
||||
Create and configure the FastAPI application.
|
||||
"""
|
||||
app = FastAPI(
|
||||
title="GSPro Remote",
|
||||
version="0.1.0",
|
||||
description="Remote control API for GSPro golf simulator",
|
||||
docs_url="/api/docs",
|
||||
redoc_url="/api/redoc",
|
||||
openapi_url="/api/openapi.json",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# Configure CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"], # In production, specify actual origins
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Mount API routers
|
||||
app.include_router(actions.router, prefix="/api/actions", tags=["Actions"])
|
||||
app.include_router(config.router, prefix="/api/config", tags=["Configuration"])
|
||||
app.include_router(vision.router, prefix="/api/vision", tags=["Vision"])
|
||||
app.include_router(system.router, prefix="/api/system", tags=["System"])
|
||||
|
||||
# Serve frontend UI if built
|
||||
ui_path = Path(__file__).parent.parent / "ui"
|
||||
if ui_path.exists():
|
||||
app.mount("/ui", StaticFiles(directory=str(ui_path), html=True), name="ui")
|
||||
logger.info(f"Serving UI from {ui_path}")
|
||||
|
||||
# Root redirect
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {
|
||||
"name": "GSPro Remote",
|
||||
"version": "0.1.0",
|
||||
"status": "running",
|
||||
"ui": "/ui" if ui_path.exists() else None,
|
||||
"docs": "/api/docs",
|
||||
}
|
||||
|
||||
return app
|
||||
|
||||
|
||||
# Create the application instance
|
||||
app = create_app()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
config = get_config()
|
||||
uvicorn.run("app.main:app", host=config.server.host, port=config.server.port, reload=True, log_level="info")
|
||||
Loading…
Add table
Add a link
Reference in a new issue