"""Picture target schemas (CRUD, processing state, settings, metrics).""" from datetime import datetime from typing import Dict, List, Literal, Optional from pydantic import BaseModel, Field from wled_controller.core.processor_manager import DEFAULT_STATE_CHECK_INTERVAL class ColorCorrection(BaseModel): """Color correction settings.""" gamma: float = Field(default=2.2, description="Gamma correction", ge=0.1, le=5.0) saturation: float = Field(default=1.0, description="Saturation multiplier", ge=0.0, le=2.0) brightness: float = Field(default=1.0, description="Brightness multiplier", ge=0.0, le=1.0) class ProcessingSettings(BaseModel): """Processing settings for a picture target.""" display_index: int = Field(default=0, description="Display to capture", ge=0) fps: int = Field(default=30, description="Target frames per second", ge=10, le=90) border_width: int = Field(default=10, description="Border width in pixels", ge=1, le=100) interpolation_mode: str = Field(default="average", description="LED color interpolation mode (average, median, dominant)") brightness: float = Field(default=1.0, description="Global brightness (0.0-1.0)", ge=0.0, le=1.0) smoothing: float = Field(default=0.3, description="Temporal smoothing factor (0.0=none, 1.0=full)", ge=0.0, le=1.0) state_check_interval: int = Field( default=DEFAULT_STATE_CHECK_INTERVAL, ge=5, le=600, description="Seconds between WLED health checks" ) color_correction: Optional[ColorCorrection] = Field( default_factory=ColorCorrection, description="Color correction settings" ) class PictureTargetCreate(BaseModel): """Request to create a picture target.""" name: str = Field(description="Target name", min_length=1, max_length=100) target_type: str = Field(default="wled", description="Target type (wled)") device_id: str = Field(default="", description="WLED device ID") picture_source_id: str = Field(default="", description="Picture source ID") settings: Optional[ProcessingSettings] = Field(None, description="Processing settings") description: Optional[str] = Field(None, description="Optional description", max_length=500) class PictureTargetUpdate(BaseModel): """Request to update a picture target.""" name: Optional[str] = Field(None, description="Target name", min_length=1, max_length=100) device_id: Optional[str] = Field(None, description="WLED device ID") picture_source_id: Optional[str] = Field(None, description="Picture source ID") settings: Optional[ProcessingSettings] = Field(None, description="Processing settings") description: Optional[str] = Field(None, description="Optional description", max_length=500) class PictureTargetResponse(BaseModel): """Picture target response.""" id: str = Field(description="Target ID") name: str = Field(description="Target name") target_type: str = Field(description="Target type") device_id: str = Field(default="", description="WLED device ID") picture_source_id: str = Field(default="", description="Picture source ID") settings: ProcessingSettings = Field(description="Processing settings") description: Optional[str] = Field(None, description="Description") created_at: datetime = Field(description="Creation timestamp") updated_at: datetime = Field(description="Last update timestamp") class PictureTargetListResponse(BaseModel): """List of picture targets response.""" targets: List[PictureTargetResponse] = Field(description="List of picture targets") count: int = Field(description="Number of targets") class TargetProcessingState(BaseModel): """Processing state for a picture target.""" target_id: str = Field(description="Target ID") device_id: str = Field(description="Device ID") processing: bool = Field(description="Whether processing is active") fps_actual: Optional[float] = Field(None, description="Actual FPS achieved") fps_target: int = Field(description="Target FPS") display_index: int = Field(description="Current display index") last_update: Optional[datetime] = Field(None, description="Last successful update") errors: List[str] = Field(default_factory=list, description="Recent errors") wled_online: bool = Field(default=False, description="Whether WLED device is reachable") wled_latency_ms: Optional[float] = Field(None, description="WLED health check latency in ms") wled_name: Optional[str] = Field(None, description="WLED device name") wled_version: Optional[str] = Field(None, description="WLED firmware version") wled_led_count: Optional[int] = Field(None, description="LED count reported by WLED device") wled_rgbw: Optional[bool] = Field(None, description="Whether WLED device uses RGBW LEDs") wled_led_type: Optional[str] = Field(None, description="LED chip type (e.g. WS2812B, SK6812 RGBW)") wled_last_checked: Optional[datetime] = Field(None, description="Last health check time") wled_error: Optional[str] = Field(None, description="Last health check error") class TargetMetricsResponse(BaseModel): """Target metrics response.""" target_id: str = Field(description="Target ID") device_id: str = Field(description="Device ID") processing: bool = Field(description="Whether processing is active") fps_actual: Optional[float] = Field(None, description="Actual FPS") fps_target: int = Field(description="Target FPS") uptime_seconds: float = Field(description="Processing uptime in seconds") frames_processed: int = Field(description="Total frames processed") errors_count: int = Field(description="Total error count") last_error: Optional[str] = Field(None, description="Last error message") last_update: Optional[datetime] = Field(None, description="Last update timestamp")