Refactor capture engine architecture, rename PictureStream to PictureSource, and split API modules
- Separate CaptureEngine into stateless factory + stateful CaptureStream session - Add LiveStream/LiveStreamManager for shared capture with reference counting - Rename PictureStream to PictureSource across storage, API, and UI - Remove legacy migration logic and unused compatibility code - Split monolithic routes.py (1935 lines) into 5 focused route modules - Split schemas.py (480 lines) into 7 schema modules with re-exports - Extract dependency injection into dedicated dependencies.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
93
server/src/wled_controller/api/routes/system.py
Normal file
93
server/src/wled_controller/api/routes/system.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""System routes: health, version, displays."""
|
||||
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from wled_controller import __version__
|
||||
from wled_controller.api.auth import AuthRequired
|
||||
from wled_controller.api.schemas.system import (
|
||||
DisplayInfo,
|
||||
DisplayListResponse,
|
||||
HealthResponse,
|
||||
VersionResponse,
|
||||
)
|
||||
from wled_controller.core.screen_capture import get_available_displays
|
||||
from wled_controller.utils import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/health", response_model=HealthResponse, tags=["Health"])
|
||||
async def health_check():
|
||||
"""Check service health status.
|
||||
|
||||
Returns basic health information including status, version, and timestamp.
|
||||
"""
|
||||
logger.info("Health check requested")
|
||||
|
||||
return HealthResponse(
|
||||
status="healthy",
|
||||
timestamp=datetime.utcnow(),
|
||||
version=__version__,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/api/v1/version", response_model=VersionResponse, tags=["Info"])
|
||||
async def get_version():
|
||||
"""Get version information.
|
||||
|
||||
Returns application version, Python version, and API version.
|
||||
"""
|
||||
logger.info("Version info requested")
|
||||
|
||||
return VersionResponse(
|
||||
version=__version__,
|
||||
python_version=f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
||||
api_version="v1",
|
||||
)
|
||||
|
||||
|
||||
@router.get("/api/v1/config/displays", response_model=DisplayListResponse, tags=["Config"])
|
||||
async def get_displays(_: AuthRequired):
|
||||
"""Get list of available displays.
|
||||
|
||||
Returns information about all available monitors/displays that can be captured.
|
||||
"""
|
||||
logger.info("Listing available displays")
|
||||
|
||||
try:
|
||||
# Get available displays with all metadata (name, refresh rate, etc.)
|
||||
display_dataclasses = get_available_displays()
|
||||
|
||||
# Convert dataclass DisplayInfo to Pydantic DisplayInfo
|
||||
displays = [
|
||||
DisplayInfo(
|
||||
index=d.index,
|
||||
name=d.name,
|
||||
width=d.width,
|
||||
height=d.height,
|
||||
x=d.x,
|
||||
y=d.y,
|
||||
is_primary=d.is_primary,
|
||||
refresh_rate=d.refresh_rate,
|
||||
)
|
||||
for d in display_dataclasses
|
||||
]
|
||||
|
||||
logger.info(f"Found {len(displays)} displays")
|
||||
|
||||
return DisplayListResponse(
|
||||
displays=displays,
|
||||
count=len(displays),
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get displays: {e}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"Failed to retrieve display information: {str(e)}"
|
||||
)
|
||||
Reference in New Issue
Block a user