Move FPS from color strip source to target; dynamic capture rate
FPS is a consumption property (how fast to send to a device), not a production property. Two targets sharing the same source may need different FPS. This moves the fps field from PictureColorStripSource to WledPictureTarget across the full stack. The capture stream now auto-adjusts its rate to max(all connected target FPS values) via ColorStripStreamManager tracking per-consumer FPS. UI updates: FPS slider in target editor, FPS badge on target cards, LED count repositioned in CSS editor, consistent speed icons. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -59,7 +59,6 @@ def _css_to_response(source, overlay_active: bool = False) -> ColorStripSourceRe
|
||||
name=source.name,
|
||||
source_type=source.source_type,
|
||||
picture_source_id=getattr(source, "picture_source_id", None),
|
||||
fps=getattr(source, "fps", None),
|
||||
brightness=getattr(source, "brightness", None),
|
||||
saturation=getattr(source, "saturation", None),
|
||||
gamma=getattr(source, "gamma", None),
|
||||
@@ -127,7 +126,6 @@ async def create_color_strip_source(
|
||||
name=data.name,
|
||||
source_type=data.source_type,
|
||||
picture_source_id=data.picture_source_id,
|
||||
fps=data.fps,
|
||||
brightness=data.brightness,
|
||||
saturation=data.saturation,
|
||||
gamma=data.gamma,
|
||||
@@ -187,7 +185,6 @@ async def update_color_strip_source(
|
||||
source_id=source_id,
|
||||
name=data.name,
|
||||
picture_source_id=data.picture_source_id,
|
||||
fps=data.fps,
|
||||
brightness=data.brightness,
|
||||
saturation=data.saturation,
|
||||
gamma=data.gamma,
|
||||
|
||||
@@ -94,6 +94,7 @@ def _target_to_response(target) -> PictureTargetResponse:
|
||||
target_type=target.target_type,
|
||||
device_id=target.device_id,
|
||||
color_strip_source_id=target.color_strip_source_id,
|
||||
fps=target.fps,
|
||||
standby_interval=target.standby_interval,
|
||||
state_check_interval=target.state_check_interval,
|
||||
description=target.description,
|
||||
@@ -148,6 +149,7 @@ async def create_target(
|
||||
target_type=data.target_type,
|
||||
device_id=data.device_id,
|
||||
color_strip_source_id=data.color_strip_source_id,
|
||||
fps=data.fps,
|
||||
standby_interval=data.standby_interval,
|
||||
state_check_interval=data.state_check_interval,
|
||||
picture_source_id=data.picture_source_id,
|
||||
@@ -243,6 +245,7 @@ async def update_target(
|
||||
name=data.name,
|
||||
device_id=data.device_id,
|
||||
color_strip_source_id=data.color_strip_source_id,
|
||||
fps=data.fps,
|
||||
standby_interval=data.standby_interval,
|
||||
state_check_interval=data.state_check_interval,
|
||||
picture_source_id=data.picture_source_id,
|
||||
@@ -254,7 +257,8 @@ async def update_target(
|
||||
try:
|
||||
target.sync_with_manager(
|
||||
manager,
|
||||
settings_changed=(data.standby_interval is not None or
|
||||
settings_changed=(data.fps is not None or
|
||||
data.standby_interval is not None or
|
||||
data.state_check_interval is not None or
|
||||
data.key_colors_settings is not None),
|
||||
source_changed=data.color_strip_source_id is not None,
|
||||
|
||||
@@ -34,7 +34,6 @@ class ColorStripSourceCreate(BaseModel):
|
||||
source_type: Literal["picture", "static", "gradient", "color_cycle"] = Field(default="picture", description="Source type")
|
||||
# picture-type fields
|
||||
picture_source_id: str = Field(default="", description="Picture source ID (for picture type)")
|
||||
fps: int = Field(default=30, description="Target frames per second", ge=10, le=90)
|
||||
brightness: float = Field(default=1.0, description="Brightness multiplier (0.0-2.0)", ge=0.0, le=2.0)
|
||||
saturation: float = Field(default=1.0, description="Saturation (0.0=grayscale, 1.0=unchanged, 2.0=double)", ge=0.0, le=2.0)
|
||||
gamma: float = Field(default=1.0, description="Gamma correction (1.0=none, <1=brighter, >1=darker mids)", ge=0.1, le=3.0)
|
||||
@@ -61,7 +60,6 @@ class ColorStripSourceUpdate(BaseModel):
|
||||
name: Optional[str] = Field(None, description="Source name", min_length=1, max_length=100)
|
||||
# picture-type fields
|
||||
picture_source_id: Optional[str] = Field(None, description="Picture source ID")
|
||||
fps: Optional[int] = Field(None, description="Target FPS", ge=10, le=90)
|
||||
brightness: Optional[float] = Field(None, description="Brightness multiplier (0.0-2.0)", ge=0.0, le=2.0)
|
||||
saturation: Optional[float] = Field(None, description="Saturation (0.0-2.0)", ge=0.0, le=2.0)
|
||||
gamma: Optional[float] = Field(None, description="Gamma correction (0.1-3.0)", ge=0.1, le=3.0)
|
||||
@@ -90,7 +88,6 @@ class ColorStripSourceResponse(BaseModel):
|
||||
source_type: str = Field(description="Source type")
|
||||
# picture-type fields
|
||||
picture_source_id: Optional[str] = Field(None, description="Picture source ID")
|
||||
fps: Optional[int] = Field(None, description="Target FPS")
|
||||
brightness: Optional[float] = Field(None, description="Brightness multiplier")
|
||||
saturation: Optional[float] = Field(None, description="Saturation")
|
||||
gamma: Optional[float] = Field(None, description="Gamma correction")
|
||||
|
||||
@@ -53,6 +53,7 @@ class PictureTargetCreate(BaseModel):
|
||||
# LED target fields
|
||||
device_id: str = Field(default="", description="LED device ID")
|
||||
color_strip_source_id: str = Field(default="", description="Color strip source ID")
|
||||
fps: int = Field(default=30, ge=10, le=90, description="Target send FPS (10-90)")
|
||||
standby_interval: float = Field(default=1.0, description="Keepalive send interval when screen is static (0.5-5.0s)", ge=0.5, le=5.0)
|
||||
state_check_interval: int = Field(default=DEFAULT_STATE_CHECK_INTERVAL, description="Device health check interval (5-600s)", ge=5, le=600)
|
||||
# KC target fields
|
||||
@@ -68,6 +69,7 @@ class PictureTargetUpdate(BaseModel):
|
||||
# LED target fields
|
||||
device_id: Optional[str] = Field(None, description="LED device ID")
|
||||
color_strip_source_id: Optional[str] = Field(None, description="Color strip source ID")
|
||||
fps: Optional[int] = Field(None, ge=10, le=90, description="Target send FPS (10-90)")
|
||||
standby_interval: Optional[float] = Field(None, description="Keepalive interval (0.5-5.0s)", ge=0.5, le=5.0)
|
||||
state_check_interval: Optional[int] = Field(None, description="Health check interval (5-600s)", ge=5, le=600)
|
||||
# KC target fields
|
||||
@@ -85,6 +87,7 @@ class PictureTargetResponse(BaseModel):
|
||||
# LED target fields
|
||||
device_id: str = Field(default="", description="LED device ID")
|
||||
color_strip_source_id: str = Field(default="", description="Color strip source ID")
|
||||
fps: Optional[int] = Field(None, description="Target send FPS")
|
||||
standby_interval: float = Field(default=1.0, description="Keepalive interval (s)")
|
||||
state_check_interval: int = Field(default=DEFAULT_STATE_CHECK_INTERVAL, description="Health check interval (s)")
|
||||
# KC target fields
|
||||
|
||||
Reference in New Issue
Block a user