Files
ledgrab/server/src/wled_controller/api/schemas/picture_sources.py
T
alexei.dolgolyov ee52e2d98f Animation None option, FPS min 1, serial COM lifecycle fixes
- Replace animation Enable checkbox with None option in effect selector;
  show effect description tooltip; disable speed slider when None selected
- Allow target FPS range 1-90 (was 10-90) across UI and backend validation
- Scope serial COM connections to target lifetime (no idle caching);
  use temporary connections for power-off/test mode
- Fix serial black frame on stop: flush after write, delay after task
  cancel to prevent race with in-flight thread pool write

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:33:56 +03:00

81 lines
4.2 KiB
Python

"""Picture source schemas."""
from datetime import datetime
from typing import List, Literal, Optional
from pydantic import BaseModel, Field
class PictureSourceCreate(BaseModel):
"""Request to create a picture source."""
name: str = Field(description="Stream name", min_length=1, max_length=100)
stream_type: Literal["raw", "processed", "static_image"] = Field(description="Stream type")
display_index: Optional[int] = Field(None, description="Display index (raw streams)", ge=0)
capture_template_id: Optional[str] = Field(None, description="Capture template ID (raw streams)")
target_fps: Optional[int] = Field(None, description="Target FPS (raw streams)", ge=1, le=90)
source_stream_id: Optional[str] = Field(None, description="Source stream ID (processed streams)")
postprocessing_template_id: Optional[str] = Field(None, description="Postprocessing template ID (processed streams)")
image_source: Optional[str] = Field(None, description="Image URL or file path (static_image streams)")
description: Optional[str] = Field(None, description="Stream description", max_length=500)
class PictureSourceUpdate(BaseModel):
"""Request to update a picture source."""
name: Optional[str] = Field(None, description="Stream name", min_length=1, max_length=100)
display_index: Optional[int] = Field(None, description="Display index (raw streams)", ge=0)
capture_template_id: Optional[str] = Field(None, description="Capture template ID (raw streams)")
target_fps: Optional[int] = Field(None, description="Target FPS (raw streams)", ge=1, le=90)
source_stream_id: Optional[str] = Field(None, description="Source stream ID (processed streams)")
postprocessing_template_id: Optional[str] = Field(None, description="Postprocessing template ID (processed streams)")
image_source: Optional[str] = Field(None, description="Image URL or file path (static_image streams)")
description: Optional[str] = Field(None, description="Stream description", max_length=500)
class PictureSourceResponse(BaseModel):
"""Picture source information response."""
id: str = Field(description="Stream ID")
name: str = Field(description="Stream name")
stream_type: str = Field(description="Stream type (raw, processed, or static_image)")
display_index: Optional[int] = Field(None, description="Display index")
capture_template_id: Optional[str] = Field(None, description="Capture template ID")
target_fps: Optional[int] = Field(None, description="Target FPS")
source_stream_id: Optional[str] = Field(None, description="Source stream ID")
postprocessing_template_id: Optional[str] = Field(None, description="Postprocessing template ID")
image_source: Optional[str] = Field(None, description="Image URL or file path")
created_at: datetime = Field(description="Creation timestamp")
updated_at: datetime = Field(description="Last update timestamp")
description: Optional[str] = Field(None, description="Stream description")
class PictureSourceListResponse(BaseModel):
"""List of picture sources response."""
streams: List[PictureSourceResponse] = Field(description="List of picture sources")
count: int = Field(description="Number of streams")
class PictureSourceTestRequest(BaseModel):
"""Request to test a picture source."""
capture_duration: float = Field(default=5.0, ge=0.0, le=30.0, description="Duration to capture in seconds (0 = single frame)")
border_width: int = Field(default=10, ge=1, le=100, description="Border width in pixels for preview")
class ImageValidateRequest(BaseModel):
"""Request to validate an image source (URL or file path)."""
image_source: str = Field(description="Image URL or local file path")
class ImageValidateResponse(BaseModel):
"""Response from image validation."""
valid: bool = Field(description="Whether the image source is accessible and valid")
width: Optional[int] = Field(None, description="Image width in pixels")
height: Optional[int] = Field(None, description="Image height in pixels")
preview: Optional[str] = Field(None, description="Base64-encoded JPEG thumbnail")
error: Optional[str] = Field(None, description="Error message if invalid")